Files

查找並複制包含文件類型的目錄

  • September 1, 2017

我有一個目錄“電影”,其中包含子目錄“電影名稱”。每個子目錄“電影名稱”包含一個電影文件和相關的圖像/nfo 文件等。

我正在嘗試將包含“.avi”類型的電影文件的所有目錄複製到外部 USB 設備。

因此,如果Directory/subdirectory A包含movie.avi, poster.jpgmovie.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 -Rprsync -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

引用自:https://unix.stackexchange.com/questions/75605