Shell

根據文件類型和日期查找和移動目錄

  • January 21, 2016

我有一個目錄“新電影”,其中包含 200 多個子目錄“電影名稱(年份)”。子目錄“電影名稱(年份)”包含一個影片文件(avi/mkv)和幾個相關的 jpg/xml 文件。

我需要將包含至少 180 天前的影片文件的所有目錄移動到另一個目錄。

例如:

新電影/電影 A(年)將包含 movie.mkv、folder.jpg 和 movie.xml,我想將它們移動到其他地方的同名子目錄,所有文件都存在且完好無損。

在本網站的其他地方查看後,我嘗試過:

cd "/mnt/user/New Movies/"
find -type f \( -name "*.avi" -or -name ".*mkv" \) -mtime +180 -exec sh -c 'mv "${0%/*}" /mnt/user/Movies' {} \;

該命令成功地將第一個子目錄和所有文件移動到它們的新首頁,但是在此之後的每個操作都會返回錯誤

find: './Movie B (year)': No such file or directory
find: './Movie C (year)': No such file or directory

等等通過“新電影”下包含的所有目錄,無論它們是否應該被移動。

不要-exec mv目前正在檢查的目錄find。當你這樣做時,似乎find會感到困惑。

解決方法:首先找到目錄,然後移動它們。

cd "/mnt/user/New Movies/"
find -type f \( -name "*.avi" -or -name ".*mkv" \) -mtime +180 \
 -printf "%h\0" | xargs -0 mv -t /mnt/user/Movies

解釋:

  • -printf根據格式字元串列印匹配。
  • %h列印匹配的路徑部分。這對應"${0%/*}"於您的命令中的 。
  • \0使用空字元分隔項目。如果文件名包含換行符,這只是預防措施。
  • xargs從管道收集輸入,然後在附加輸入的情況下執行其參數。
  • -0告訴 xargs 期望輸入以空值分隔而不是換行符分隔。
  • mv -t <target>允許mv在最後附加所有源參數的情況下呼叫。

請注意,這仍然不是絕對安全的。一些怪異的調度程序計時結合管道緩衝區可能仍會導致在移出目錄mv之前執行。find為了防止這種情況,您可以這樣做:

cd "/mnt/user/New Movies/"
find -type f \( -name "*.avi" -or -name ".*mkv" \) -mtime +180 \
 -printf "%h\0" > dirstomove
xargs -0 mv -t /mnt/user/Movies < dirstomove

背景說明:

我假設您find的情況如下:

  1. find遍歷目錄/mnt/user/New Movies/。在那裡,它會記下其記憶體中的可用目錄。
  2. find使用系統呼叫遍歷其中一個子目錄chdir(subdirname)
  3. 在裡面find找到一個通過過濾器的電影文件。
  4. find``mv使用給定的參數執行。
  5. mv將目錄移動到/mnt/user/Movies.
  6. find使用系統呼叫返回父目錄chdir(..),現在指向/mnt/user/Movies而不是/mnt/user/New Movies/
  7. find很困惑,因為它沒有找到前面提到的目錄並引發了很多錯誤。

這個假設是基於這個問題的答案:find -exec mv 在第一個 exec 之後停止。我不知道為什麼find在這種情況下停止工作並在您的情況下引發錯誤。不同版本的find可能是解釋。

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