Xargs

使用 xargs 執行多個命令

  • October 4, 2016

是否可以使用 find + xargs 來呼叫多個命令?我正在嘗試查找大小大於 100 個字元的所有文件。並且少於 1000 個字元,更改他們的權限並將文件列表列印到文件中。我可以用 exec 例如

find . -maxdepth 1 -size +100c -size -1000c -exec chmod a+r {} \; -print > testfile

但是有什麼方法可以用 xargs 實現這一點嗎?

  find . -maxdepth 1 -size +100c -size -1000c -print0 | xargs -0 -I '{}' chmod a+r '{}' -print >testfile

最後一次列印不會執行或拋出錯誤。有沒有辦法用 xargs 來實現它?

您在這裡不需要任何 GNUisms(並且您可能想要一個-mindepth 1to exclude .),並且您不需要為chmod每個文件執行一個:

find . ! -name . -prune ! -type l -size +100c -size -1000c -print \
 -exec chmod a+r {} + >testfile

(我還添加了一個! -type l因為-size會檢查符號連結的大小,同時chmod會更改符號連結目標的權限,因此考慮符號連結沒有意義。您可能想走得更遠,只考慮正常文件 ( -type f))

這在這裡有效,因為chmod它不會在其標準輸出上輸出任何內容(否則最終會出現在測試文件中)。

更一般地說,為避免這種情況,您需要執行以下操作:

find . ! -name . -prune ! -type l -size +100c -size -1000c -print -exec sh -c '
 exec cmd-that-may-write-to-stdout "$@" >&3 3>&-' sh {} + 3>&1 > testfile 

所以find’s stdout 轉到testfilecmd-that-may-write-to-stdout’s stdout 在重定向之前轉到原始 stdout(如上保存3>&1)。

請注意,在您的:

find . -maxdepth 1 -size +100c -size -1000c -exec chmod a+r {} \; -print > testfile

testfile將包含chmod已經成功的文件(在-print之後的-exec意思-exec是那個的另一個條件,如果執行的命令以非零退出狀態返回,則成功)-print-exec

如果你想使用xargs(這裡使用 GNU 語法),你可以使用tee和處理替換:

find . ! -name . -prune ! -type l -size +100c -size -1000c -print0 |
  tee >(tr '\0' '\n' > testfile) |
  xargs -r0 chmod a+r

find將NUL 轉換為換行符的輸出保存到testfile. 但是請注意,該tr命令在後台執行。您的 shell 會等待xargs(至少,大多數 shell 也會等待teeand find),但不會等待tr. 因此,在 shell 執行下一個命令時,有一點可能tr已經完成了數據的寫入。testfile如果testfile到那時完全寫入比修改所有權限更重要,您可能需要交換上面的xargsandtr命令。

另一種選擇是將上面的整個程式碼包裝在:

(<that-code>) 3>&1 | cat

這樣,shell 將等待cat並且只有在它讀取的管道(包括, , , )cat的寫入端打開文件描述符 3 的所有程序都退出時才會退出。tr``find``tee``xargs

另一種選擇是在此處使用zshglob:

files=(./*(L+100L-1000^@))
chmod a+r $files
print -rl $files > testfile

儘管如果文件列表很大,您可能會遇到太多參數錯誤。find -exec +xargs在需要時通過執行多個chmod命令來解決此問題。你可以使用zargsin zsh

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