我有一個目錄,其中有一些 C 程式檔案和一個帶有這些 C 檔案可執行檔案的 Makefile。我可以簡單地運行它來一次洗掉所有可執行檔案rm !(*.c|Makefile)。
但是當我將它添加到我的makefile時
CFLAGS= -Wall -g -lm
SHELL=/bin/bash
careful:
echo "nothing"
clean:
rm -i !(*.c|Makefile)
執行命令時出現此錯誤
/bin/bash: -c: line 1: syntax error near unexpected token `('
/bin/bash: -c: line 1: `rm -i !(*.c|Makefile)'
make: *** [Makefile:8: clean] Error 2
我對 Bash 語法不太了解,但我知道它()被視為子 shell,我認為這就是為什么我不能rm (*.c)直接在終端中運行,因為*.c它不是命令(或任何有效語法)。但是rm -i !(*.c)在終端中運行有效。所以我想!()在 Bash 中會受到不同的對待。
我對這一切的假設:在我運行的 Makefile 中,make clean它處理 !(*.c|Makefile),與普通終端不同,或者以某種方式!忽略!(*.c|Makefile)
所以我的問題是:
- 在 Bash 中是否有不同
!()的處理方式?() - 為什么
!(wildcard)在終端作業但不在我的Makefile - 我怎樣才能使它在中作業
Makefile?
uj5u.com熱心網友回復:
對于非互動式 shell,沒有開箱即用地啟用特定于 Bash 的擴展通配模式。
!(...)純粹是這種通配符語法的一部分,與子shell 無關。
無論如何,可能更好的解決方案是重構它,這樣您就不必依賴 Bash。
.PHONY: clean
clean:
rm -i $(filter-out $(wildcard *.c) Makefile,$(wildcard *))
Bash 參考手冊沒有很好的鏈接錨點,但可用的擴展通配符語法extglob在模式匹配部分中描述
如果你真的想要,你也可以shopt -s extglob在你Makefile的 . 例如,
.PHONY: clean
clean:
shopt -s extglob; \
eval 'rm -i !(*.c|Makefile)'
還要注意如何shopt以及eval需要在同一邏輯行上,因為make開箱即用地在單獨的新 shell 實體中執行每個配方行(盡管您可以使用 更改它.ONESHELL)
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/446316.html
