查找並複制包含文件類型的目錄
我有一個目錄“電影”,其中包含子目錄“電影名稱”。每個子目錄“電影名稱”包含一個電影文件和相關的圖像/nfo 文件等。
我正在嘗試將包含“.avi”類型的電影文件的所有目錄複製到外部 USB 設備。
因此,如果
Directory/subdirectory A
包含movie.avi
,poster.jpg
和movie.nfo
,那麼我想將該目錄及其內容複製到外部驅動器。我試過這個:
find . -name "*.avi" -printf "%h\n" -exec cp {} /share/USBDisk1/Movies/ \;
但它只複製文件,而不是目錄和文件內容。
首先,為什麼您的嘗試不起作用:列印文件名
-printf "%h\n"
的目錄部分。.avi
這不會影響後續-exec
操作中的任何內容 -{}
並不意味著“無論最後printf
列印什麼命令”,它意味著“找到的文件的路徑”。如果要在該
cp
命令中使用文件名的目錄部分,則需要在將文件名傳遞給cp
. 該find
命令沒有此功能,但 shell 有,因此find
請呼叫一個呼叫cp
.find . -name "*.avi" -exec sh -c 'cp -Rp "${0%/*}" /share/USBDisk1/Movies/' {} \;
請注意,由於您正在複製目錄,因此您需要傳遞
-r
到。cp
您也應該使用-p
.您可以有用地替換
cp -Rp
為rsync -a
. 這樣,如果您已經複製了電影目錄,則不會再次複製它(除非其內容已更改)。您的命令有一個可能會或可能不會影響您的缺陷:如果一個目錄包含多個
.avi
文件,它將被複製多次。最好查找目錄,如果它們包含.avi
文件,則複製它們,而不是查找.avi
文件。如果你使用rsync
而不是,文件將不會被再次複製,只是為了一遍又一遍地驗證文件的存在而做cp
更多的工作。rsync
如果所有電影目錄都直接在頂層目錄下,則不需要
find
,萬用字元模式上的簡單循環就足夠了。for d in ./*/; do set -- "$d/"*.avi if [ -e "$1" ]; then # there is at least one .avi file in $d cp -rp -- "$d" /share/USBDisk1/Movies/ fi done
如果電影目錄可能是嵌套的(例如
Movies/science fiction/Ridley Scott/Blade Runner
),則不需要find
,萬用字元模式上的簡單循環就足夠了。您確實需要執行 ksh93 或 bash ≥4 或 zsh,並且在 ksh93 中您需要先執行set -o globstar
,在 bash 中您需要先執行shopt -s globstar
。萬用字元模式**/
遞歸地匹配目前目錄及其所有子目錄(bash 還遍歷子目錄的符號連結)。for d in ./**/; do set -- "$d/"*.avi if [ -e "$1" ]; then cp -rp -- "$d" /share/USBDisk1/Movies/ fi done