使用find命令的Makefile报错:paths must precede expression
问题:Makefile中find命令报错“paths must precede expression”
我编写了如下Makefile,用来查找所有以"slides"为前缀的.tex文件并编译成PDF:
TSLIDES = $(shell find . -maxdepth 1 -iname 'slides*.tex' -printf '%f ') TPDFS = $(TSLIDES:%.tex=%.pdf) all: $(TPDFS) $(TPDFS): %.pdf: %.tex latexmk -pdf $<
但持续收到错误信息(之前能正常运行,现在突然报错):
/usr/bin/find: paths must precede expression: `slides01-intro.tex' /usr/bin/find: possible unquoted pattern after predicate `-iname'?
我查了find的手册,里面提到这类错误通常是通配符被shell展开导致的,需要用引号或转义包裹,但我已经用单引号了,问题依然存在。尝试去掉-printf参数后还是报同样的错。补充:我使用Windows系统,用的是Git Bash(基于mingw-64)。
解决方法
原因分析
在Windows的Git Bash环境下,Make处理$(shell)时会先移除单引号,导致slides*.tex被Bash直接展开成当前目录下所有匹配的文件名。此时find命令收到的参数变成了find . -maxdepth 1 -iname slides01-intro.tex slides02-xxx.tex ...,find会把后面的文件名当成路径参数,从而触发“paths must precede expression”错误。
可行方案
用双引号包裹通配符
双引号会被Make保留并传递给Bash,能有效阻止通配符展开:TSLIDES = $(shell find . -maxdepth 1 -iname "slides*.tex" -printf '%f\n')转义通配符
用反斜杠转义星号,避免Bash展开:TSLIDES = $(shell find . -maxdepth 1 -iname slides\*.tex -printf '%f\n')改用Make内置的通配符功能(推荐)
直接用Make的wildcard函数替代find,更简洁且跨环境兼容性更好:TSLIDES = $(wildcard slides*.tex) TPDFS = $(TSLIDES:%.tex=%.pdf) all: $(TPDFS) %.pdf: %.tex latexmk -pdf $<
内容的提问来源于stack exchange,提问作者Giuseppe
相关产品推荐
相关产品推荐

