修改 zsh 通配模式以與 cp 一起使用

修改 zsh 通配模式以與 cp 一起使用

我正在嘗試編寫一個腳本來從 files 以外的特定資料夾中遞歸複製文件A.extn,其中B/*.extn和是目錄,並且只是一些通用擴展名。這就是我所擁有的:C/*BCextn

#!/usr/local/bin/zsh
setopt EXTENDED_GLOB
TMPDIR=/tmp/test

cp -pR $(dirname $0)/**~(*.foo/*|*/bar.txt|*.abc|qux.txt) $TMPDIR

然而,這並沒有如預期地對模式進行否定。我想我確實知道為什麼 - 儘管模式是正確的(如 所示echo),cp -R但不知道該模式,並進入了一個“不應該”的目錄,一旦進入該目錄,該模式就不再有效。

我該如何修改上面的內容來達到我想要的效果?我想用findand是可能的xargs,但我被上面的清晰性所吸引,並且更喜歡類似的東西(但如果這是錯誤的方法,我會非常高興有一個不同的解決方案)。

答案1

您是正確的,該模式在cp運行之前已擴展,因此該命令未知。

您可以透過使用選項--parentstocp而不是 來完成您想要的任務-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

相關內容