linux - Makefile - make 找到一个文件,而 shell 没有
问题描述
我编写了一个 Makefile 片段,用于在执行rm之前检查文件是否存在。
clean:
echo "Attempt to remove $(exec) file"
if test -f "${exec}" ; then \
echo "Removing file ${exec}" ; \
rm ${exec} ; \
else \
echo "No ${exec} file to remove" ; \
fi
if "$(wildcard *.o)" = "" ; then \
echo "No files found" ; \
else \
echo " Found $(wildcard *.o) " ; \
fi
首先if语句工作正常
尝试删除 hello 文件
没有要删除的 hello 文件
而第二个产生这个:
/bin/sh: 1: main.o factorial.o: not found
main.o factorial.o
我的问题是:为什么make recipe会产生有效的输出(这些文件确实存在)而shell没有?为什么shell甚至试图找到它们?
感谢您花时间阅读这个问题。这是我的第一个,所以如果我做了不恰当的事情,请告诉我
解决方案
if main.o
与 非常不同if test -f main.o
。前者尝试运行命令main.o
,而后者运行命令test
。 if "main.o factorial.o"
类似,因为它尝试运行一个名为的命令main.o factorial.o
,shell 正确地抱怨它找不到。您的 PATH中不太可能有一个名为main.o factorial.o
(即名称中带有空格的单个文件)的文件。
但不要这样做。在取消链接之前检查文件是否存在绝对没有意义。有一个固有的竞争条件。只需尝试删除该文件,并处理如果该文件不存在可能发生的错误。
它更容易编写rm $(wildcard *.o)
,只需rm
为不存在的文件发出错误消息。或rm -f $(wildcard *.o)
抑制错误。如果您真的坚持遍历文件并检查,您可以执行以下操作:
for f in $(wildcard *.o); do \
if ! test -f "$$f"; then echo "$$f" does not exist; \
else rm "$$f"; fi
但这真的不值得。此外,这似乎毫无意义,因为wildcard
它只会扩展到存在的文件。(但请注意,这表现出相同的竞争条件:通配符可能会扩展为文件列表,但可能会在通配符扩展和rm
运行之间创建新文件。)不要这样使用wildcard
。明确列出您要使用的文件。
推荐阅读
- javascript - React & require: Error: Cannot find module "."
- react-native - Download file (fetched from API) via dynamic ID on onPress in react-native
- bazel - How can Darwin frameworks be provided to `cc_library` or `cc_binary` rules?
- python - Giving pyodbc.Error while Dockerizing a Python API/Flask APP
- akka - Lagom 是持久实体演员吗?/ 演员模型
- c# - Using params with ref keyword in C#
- swift - WKWebView 必须停止检测电话号码
- c# - C# Sql 连接字符串,尝试从另一台计算机连接到本地数据库
- d3.js - C3 条形图宽度无法正常工作
- java - Jgit 4.11 ocassionally staging all changes to commit instead of provided file pattern