
我正在嘗試編寫一個腳本來從 files 以外的特定資料夾中遞歸複製文件A.extn
,其中B/*.extn
和是目錄,並且只是一些通用擴展名。這就是我所擁有的:C/*
B
C
extn
#!/usr/local/bin/zsh
setopt EXTENDED_GLOB
TMPDIR=/tmp/test
cp -pR $(dirname $0)/**~(*.foo/*|*/bar.txt|*.abc|qux.txt) $TMPDIR
然而,這並沒有如預期地對模式進行否定。我想我確實知道為什麼 - 儘管模式是正確的(如 所示echo
),cp -R
但不知道該模式,並進入了一個“不應該”的目錄,一旦進入該目錄,該模式就不再有效。
我該如何修改上面的內容來達到我想要的效果?我想用find
and是可能的xargs
,但我被上面的清晰性所吸引,並且更喜歡類似的東西(但如果這是錯誤的方法,我會非常高興有一個不同的解決方案)。
答案1
您是正確的,該模式在cp
運行之前已擴展,因此該命令未知。
您可以透過使用選項--parents
tocp
而不是 來完成您想要的任務-R
。這只會複製與您的模式相符的文件,但將使用提供的完整路徑名,而不僅僅是尾隨文件名。
但是,這個選項不可移植。 AFAIK,只有 GNU 版本的 cp 支援它。
答案2
您的模式可能會排除您不想複製的文件,但它不會排除包含它們的目錄,並且您告訴cp
要遞歸複製。所以無論如何文件都會被複製。比這更糟的是,如果你有一個像這樣的原始碼樹
foo
foo/bar.txt
hello
hello/world
hello/world/wibble.txt
然後該模式擴展到,foo hello hello/world hello/world/wibble.txt
因此您最終會在以下位置獲得這些檔案$TMPDIR
:
foo
foo/bar.txt
hello
hello/world
hello/world/wibble.txt
wibble.txt
world
world/wibble.txt
這與模式「不再有效」無關。此模式由 shell 擴展,cp
只能看到檔案清單。
您需要使用可以在進行遞歸遍歷時排除檔案的複製工具。
您可以使用 zcp 來實現此目的,但它不會複製目錄,也不會自動建立目標目錄。完成這項工作最簡單的工具是 rsync。帕克斯是另一個選擇。
rsync -a --exclude='*.foo/*' --exclude='bar.txt' --exclude='*.abc' --exclude='/qux.txt' $(dirname $0) $TMPDIR