Terminal
僅遞歸複製與文件中列出的模式匹配的某些目錄
我有一個具有以下結構的目錄:
-- 201893208 └── 8Z12 └── ko_8Z12_Full └── wp_we_8Z12_FullDAT └── 8Z12_DATFull └── P011 └── P011_Full └── 8Z12_FullDAT └── P011_DATFull └── 9FZA └── kl_wt-we-w_kl9-9FZA_Full └── ffd-9FZA_FullDAT └── 8fdZ12232_9FZA_DATFull -- 903240920 └── P0fsa └── P0fsa_Full └── P0fsa_FullDAT └── P0fsa_DATFull └── Paaaf └── we-Paaaf_ww_fl_Full └── Paaaf_FullDAT └── Paaaf_DATFull └── 9FZATYYY └── 9FZATYYY_Full └── 9FZATYYY_FullDAT -- wt0340291 └── OPF1121 └── OPF1121_Full └── 8Z12_DATFull └── KLOFJ9 └── lop_KLOFJ9_ffj_Full └── powt_KLOFJ9_DATFull └── LP02323 └── wr_we_LP02323_Full └── wr_we_LP02323_FullDAT
上面列出的每個文件夾中都有數千個文件。然後每個里面還有很多子目錄。例如
8Z12
不僅包含上面列出的三個文件夾,而且還包含數千個文件。我只想複製名稱末尾有的目錄(不應複製DATFull目錄)並且還包含下面列表中的模式
_Full
LP02323 KLOFJ9 Paaaf 9FZA
換句話說,應該複製包含上述列表中的字元串並在其名稱中(但不是 DAT)的目錄。
Full
因此,在上面的範例中,僅應複製以下目錄(及其所有內容和子目錄):
wr_we_LP02323_Full lop_KLOFJ9_ffj_Full we-Paaaf_ww_fl_Full kl_wt-we-w_kl9-9FZA_Full
據我了解,
rsync
不支持正則表達式,因此必須首先完成find
(如果我錯了,請糾正我)。但是我怎麼能這樣做以確保檢查所有目錄和子目錄並複制所有相關文件夾,即使它們深埋在幾個子目錄中(請注意,上面的範例是簡化的我的原始文件夾的結構)。所以有兩個問題:
- 如何將模式列表提供給
find
?- 如何通過管道
find
傳輸 to的結果rsync
?到目前為止,這只是我想到的匹配
Full
:
find . -regextype sed -regex ".*/.*[^DAT]Full$"
但是如何將 ID 列表添加到此
find
命令中?
使用需要在目錄名稱中出現的字元串文件,對這些字元串進行 shell 循環,並且
rsync
(假設我們要從變數中的目錄複製到變數$source
中的目錄$target
):while IFS= read -r string; do rsync --archive --exclude='*DAT*/' --include='*/' --include="*$string*_Full/***" --exclude='*' \ --prune-empty-dirs "$source"/ "$target" done <strings.txt
選項做什麼
rsync
(對任何排除/包含模式的第一次打擊很重要):
--archive
: 複製所有權、權限、時間戳等。--exclude='*DAT*/'
: 排除DAT
名稱中帶有的任何目錄。--include='*/'
: 考慮所有目錄(前一個模式排除的目錄除外)。rsync
這是訪問您感興趣的實際目錄所必需的。--include="*$string*_Full/***"
:考慮與給定模式匹配的所有目錄以及該目錄下的所有內容。如果$string
是parrot
,這將是--include="*parrot*_Full/***"
。--exclude='*'
:不要考慮尚未明確包含的任何內容。--prune-empty-dirs
:不要傳輸沒有明確包含任何內容的目錄。如果您想查看
rsync
執行時如何評估模式,請添加-vv
到rsync
命令行。測試:
$ tree . |-- from | `-- a | `-- b | |-- c_A_DATFull | | `-- file | |-- c_A_DAT_Full | | `-- file | |-- c_A_Full | | `-- file | |-- c_B_DATFull | | `-- file | |-- c_B_DAT_Full | | `-- file | |-- c_B_Full | | `-- file | |-- c_C_DATFull | | `-- file | |-- c_C_DAT_Full | | `-- file | `-- c_C_Full | `-- file `-- strings.txt 12 directories, 10 files $ cat strings.txt A B $ source=from $ target=to
(在這裡執行循環)
$ tree . |-- from [...] `-- to `-- a `-- b |-- c_A_Full | `-- file `-- c_B_Full `-- file 17 directories, 12 files
通過一次呼叫
rsync
:set -- --exclude='*DAT*/' --include='*/' while IFS= read -r string; do set -- "$@" --include="*$string*_Full/***" done <strings.txt set -- "$@" --exclude='*' rsync --archive "$@" --prune-empty-dirs "$source"/ "$target"
一個
find
解決方案:set -- while IFS= read -r string; do set -- "$@" -o -name "*$string*_Full" done <strings.txt shift # "$@" would now be something like # -name *LP02323*_Full -o -name *Paaaf*_Full -o -name ...etc find "$source" -type d '(' "$@" ')' ! -name '*DAT*' -exec sh -c ' source=$1; target=$2; shift 2 for pathname do mkdir -p "$target/${pathname#$source}" rsync --archive "$pathname"/ "$target/${pathname#$source}" done' sh "$source" "$target" {} +
這將用於
find
生成您要複製的子目錄的列表。這些被提供給循環它們的小內聯腳本。在循環的每次迭代中,都會創建目標上的相應目錄(假定為本地副本),並使用
rsync
.永遠不要使用管道
find
將路徑名傳遞給其他命令,除非您可以安排安全地分隔路徑名。有關的: