Makefile命令替换

Makefile命令替换

我的生成文件:

all: ...(other rules) clean

clean:
    rm $(find . -type f -executable)

clean当我从上面的 Makefile 中删除规则时,一切都按预期工作。添加后,make(也make clean)命令结果为:

rm 
rm: missing operand
Try 'rm --help' for more information.
make: *** [Makefile:46: clean] Error 1

是什么原因导致这里出现问题以及如何解决?

答案1

有几个问题。

将 Makefile 中的 $ 符号传递给 shell

你想要运行命令

rm $(find . -type f -executable)

让 shell 执行命令替换。为此,您需要编写

clean:
        rm $$(find . -type f -executable)

随着 Make 本身使用的美元翻倍$

处理没有什么可“清理”的情况

如果 的输出find为空,则命令替换后

rm $(find . -type f -executable)

变成

rm

典型的rm命令会抱怨你没有告诉它要删除什么。解决这个问题的一种方法是使用xargs来处理 的输出find。它获取 的输出find,如果有任何输出,则将其分成块并运行 rm。

clean:
        find . -type f -executable | xargs rm

处理文件名中的任意字符

Unix 文件名由字符分隔的组件组成/。组件本身可以是除/和 NUL 之外的任何字符序列。特别是,组件可以包括换行符、空格、制表符、*.

对于命令替换情况 ( rm $(find . -type f -executable)) 情况,shell 将处理 find 的输出。因此,空白字符将导致分词,*字符将导致文件名“通配”发生等。为了合理的实现,xargs应避免这种情况。

如果文件名以 then 开头-,则rm可能会将它们视为命令的选项。避免这种情况的简单方法是添加--到命令中以指示“选项结束”。

剩下的主要问题是换行符。xargs将输入拆分为换行符,因此如果您有一个名为abc\ndefthen的文件,find则会输出

abc
def

并将xargs使用rm2 个文件名abcdef.

要解决此问题,请告诉findxargs使用不能出现在文件名中的 1 个字符 (NUL) 作为分隔符而不是换行符。

clean:
        find . -type f -executable -print0 | xargs -0 rm --

最好的解决方案,如果你find支持的话

clean:
        find . -type f -executable -delete

在这里您可以找到直接删除文件(如果有)。它更加高效,因为它不需要启动额外的进程。没有 shell 或 xargs 进程需要转义字符。没有特殊字符可以告诉make处理。正确处理“无文件可删除”的情况。

相关内容