You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 06:54:37