我的生成文件:
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\ndef
then的文件,find
则会输出
abc
def
并将xargs
使用rm
2 个文件名abc
和def
.
要解决此问题,请告诉find
和xargs
使用不能出现在文件名中的 1 个字符 (NUL) 作为分隔符而不是换行符。
clean:
find . -type f -executable -print0 | xargs -0 rm --
最好的解决方案,如果你find
支持的话
clean:
find . -type f -executable -delete
在这里您可以找到直接删除文件(如果有)。它更加高效,因为它不需要启动额外的进程。没有 shell 或 xargs 进程需要转义字符。没有特殊字符可以告诉make
处理。正确处理“无文件可删除”的情况。