對找到的檔案執行命令
有時我們需要針對很多檔案執行命令。這可以使用 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 擴充套件,可能無法在其他版本的 find
和 xargs
中使用。
執行此操作的首選方法是跳過 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
。