Makefile中cp命令排除文件/目录失效:!()语法在Shell中可用但Makefile执行报错
问题原因与解决方案
为什么!()语法在Makefile中失效?
虽然你已经指定了SHELL=/bin/bash,但Make在调用bash时默认会启用POSIX兼容模式(相当于传递--posix参数),而!()属于bash的extglob(扩展通配符)语法,这个特性在POSIX模式下是默认禁用的,所以会触发语法错误。
解决方法
方法1:显式开启extglob扩展
在执行cp命令前,先通过shopt -s extglob打开扩展通配符支持,注意要把这些命令放在同一个shell进程中(Makefile里每一行是单独的shell进程,所以要写在同一行或者用\连接):
修改Makefile中的build目标第一行为:
mkdir $(HASH) && shopt -s extglob && cp -r !($(HASH)) $(HASH)
方法2:改用更通用的find命令(推荐)
如果不想依赖bash的扩展特性,可以用find来实现排除指定目录的拷贝,兼容性更好:
mkdir $(HASH) && find . -maxdepth 1 -not -name "$(HASH)" -not -name "." -exec cp -r {} $(HASH)/ \;
这个命令的作用是:在当前目录下,找到除了目标目录$(HASH)和当前目录本身(.)之外的所有内容,递归拷贝到目标目录中。
验证修改后的Makefile示例
调整后的完整Makefile大概是这样:
PROJECT_NAME=nnr HASH=$(shell git log -n1 --pretty=format:%h) REVS=$(shell git log --oneline|wc -l) SHELL=/bin/bash build: mkdir $(HASH) && shopt -s extglob && cp -r !($(HASH)) $(HASH) cp INSTALL.tpl INSTALL sed -i 's/{_G_HASH}/$(HASH)/' INSTALL chmod +x INSTALL echo $(REVS).$(HASH) > $(HASH)/VERSION tar czf $(PROJECT_NAME)-$(REVS).$(HASH).tar.gz $(HASH) INSTALL rm -rf INSTALL $(HASH)
内容的提问来源于stack exchange,提问作者xrfang
相关产品推荐
相关产品推荐

