cp 除了文件在 Makefile 中不起作用

cp except a file does not work in Makefile

使用“!”的技巧使用 cp 时排除目录在 shell 下有效,但在 make 下无效:

mkdir db09601c && cp -r !(db09601c) db09601c
/usr/bin/bash: -c: line 0: syntax error near unexpected token ('
/usr/bin/bash: -c: line 0:mkdir db09601c && cp -r !(db09601c) db09601c'

我已经将 SHELL=/bin/bash 放在 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) && 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)

扩展的 glob 语法特定于 Bash。如果您愿意在 Makefile 中对 SHELL=/bin/bash 进行硬编码(您最初发布问题时并未提及),您仍然可以使用此语法(尽管您可能应该单独验证是否启用了 shopt -s extglob).

对于便携式解决方案,可能只是循环对象:

$(HASH):
    mkdir -p $(HASH)
    for f in *; do \
        case $$f in $(HASH)) continue;; esac; \
        cp -r "$$f" $(HASH); \
    done

(为了稳健性,您可能应该创建一个临时目录,并且只有在正确填充后才将其移动到最终目的地,但这留作练习。)