對找到的檔案執行命令

有時我們需要針對很多檔案執行命令。這可以使用 xargs 來完成。

find . -type d -print | xargs -r chmod 770

上面的命令將以遞迴方式查詢相對於 .(這是你當前的工作目錄)的所有目錄(-type d),並對它們執行 chmod 770。如果 find 沒有找到任何檔案,-r 選項指定 xargs 不執行 chmod

如果你的檔名或目錄中包含空格字元,則此命令可能會阻塞; 解決方案是使用以下內容

find . -type d -print0 | xargs -r -0 chmod 770

在上面的示例中,-print0-0 標誌指定使用 null 位元組分隔檔名,並允許在檔名中使用特殊字元,如空格。這是一個 GNU 擴充套件,可能無法在其他版本的 findxargs 中使用。

執行此操作的首選方法是跳過 xargs 命令,讓 find 呼叫子程序本身:

find . -type d -exec chmod 770 {} \;

這裡,{} 是一個佔位符,表示你要在該點使用檔名。find 將分別對每個檔案執行 chmod

你也可以通過使用將所有檔名傳遞給 chmod單個呼叫

find . -type d -exec chmod 770 {} +

這也是上述 xargs 片段的行為。 (要單獨呼叫每個檔案,可以使用 xargs -n1)。

第三種選擇是讓 bash 迴圈遍歷檔名 find 輸出列表:

find . -type d | while read -r d; do chmod 770 "$d"; done

這在語法上是最笨重的,但是當你想在每個找到的檔案上執行多個命令時很方便。但是,面對具有奇數名稱的檔名,這是不安全的。

find . -type f | while read -r d; do mv "$d" "${d// /_}"; done

這將用下劃線替換檔名中的所有空格。 (如果前導目錄名中有空格,此示例也不起作用。)

上面的問題是 while read -r 期望每行一個條目,但檔名可以包含換行符(並且 read -r 將丟失任何尾隨空格)。你可以通過扭轉局面來解決這個問題:

find . -type d -exec bash -c 'for f; do mv "$f" "${f// /_}"; done' _ {} +

這樣,-exec 以完全正確和便攜的形式接收檔名; bash -c 接收它們作為一些引數,可以在 $@找到,正確引用等等(當然,指令碼需要正確處理這些名稱;每個包含檔名的變數都需要用雙引號。)

神祕的 _ 是必要的,因為 bash -c 'script'的第一個引數用於填充 $0