xargs
命令讀取標準的輸入,然後使用參數作爲輸入構建和執行命令。如果沒有給出命令,那麼將使用 echo
命令。清單 12 是使用我們的 text1 文件的基礎例子,它包含 3 個行,每行只有兩個單詞。
|
爲什麼 xargs
只有一行輸出?默認情況下,xargs
在空格處中斷輸出,並且每個生成的標記都成爲一個參數。不過,當 xargs
構建命令時,它將一次傳遞儘可能多的參數。您可以使用 -n
覆蓋該行爲,或使用 --max-args
參數。在清單 13 中,我們使用了這兩種方法,併爲使用xargs
添加一個顯式的 echo
調用。
|
如果輸入包含由單引號或雙引號保護的空格,或使用了斜槓進行轉義,那麼 xargs
將不在遇到這些空格時中斷。清單 14 顯示了這些空格點。
|
到目前爲止,已經在命令的末尾添加了所有參數。如果您需要在這些參數後面再使用其他參數,可以使用 -I
選項指定一個替換字符串。如果 xargs
將要執行的命令包含有替換字符串,那麼將使用參數替換它。進行了替換之後,僅將參數傳遞給每個命令。不過,將從一整行輸出創建參數,而不僅是一個標記。您 還可以使用 xargs
的 -L
選項讓命令將行當作參數看待,而不是默認的以單個空格分隔的標記。使用 -I
選項表示 -L 1
。 清單 15 顯示了使用 -I
和 -L
選項的例子。
|
儘管我們的例子爲了便於演示使用了簡單的文本文件,您很少看到包含這樣的輸入的 xargs
。您通常需要處理某些 命令生成的大量文件,這些命令包括 ls
、find
或 grep
。清 單 16 顯示了一種通過 xargs
將目錄清單傳遞到命令(比如 grep
)的方法。
|
如果上一個例子中的一個或多個文件名包含空格,那麼會發生什麼呢?如果您像清單 16 那樣使用該命令,那麼將得到一個錯誤。在實際情況中,文件列表可能來自一些源,比如定製腳本或命令,而不是 ls
,或者您希望 通過其他管道線階段傳遞它,以進一步進行過濾。所以您應該使用 grep "1" *
取代以上構造。
對於 ls
命令,您可以使用 --quoting-style
選項強制給導致問題的文件名加上引號或進行轉義。另外一種更好的解決辦法是使用 xargs
的 -0
選項,從而使用 null 字符串 (\0) 分隔輸入參數。儘管 ls
沒有提供使用 null 字符串分隔的文件名作爲輸出的選項,但許多命令都提供這樣的選項。
在清單 17 中,我們首先將 text1 複製到 “text 1”,然後顯示一些在 xargs
命令中使用包含空格的文件名列表的方法。這些示例僅爲了演示概念,因爲 xargs
可能更加複雜。尤其是在最後一個例子中, 如果一些文件名已經包含新行字符串,那麼將新行字符串轉換成 null 字符串將導致錯誤。在本文的下一個部分中,我們將查看另外一個更加健壯的解決方案,即使用 find
命令生成合適的以 null 字符串分隔的輸出。
|
xargs
命令不會構建任意長度的命令。在 Linux 內核 2.26.3 之前,命令的長度是受限制的。針對某個包含大量名稱很長的文件的目錄的命令,比如 rm somepath/*
,可能會失敗, 返回的消息表明參數列表太長。在更舊的 Linux 系統或 UNIX 系統上仍然存在該限制,因此瞭解如何使用 xargs
以處理這種問題非常有用。
您可以使用 --show-limits
選項顯示 xargs
的默認限制,然後使用 -s
選項將輸出命令的長度限制在允許的最大字符串數量之內。查看手冊頁瞭解其他未能再次討論的選項。
使用帶有 -exec
選項或 xargs
的 find
命令
在文章 “學習 Linux,101:文件和目錄管理” 中,您學習例如如何使用 find
命令根據名稱、修改時間、大小或其他特徵查找文件。找到匹配的文件集之後,您通常希望對它們執行某些操作:刪除、移動和重命名它們等。現在我們看一下 find
命令的 -exec
選項,其功能類似於使用 find
並通過管道將輸出指向 xargs
。
|
與前面學習的 xargs
命令相比,它有幾個不同之處。
- 您必須使用 {} 標記文件名在命令中的位置。它不是自動添加在末尾的。
- 您必須使用轉義後的分號終止該命令,比如 \;、';' 或 ";" 都行。
- 該命令對每個輸入文件執行一次。
嘗試運行 find text[12] |xargs cat text3
親自看看區別在哪裏。
現在,我將話題轉回到文件名中的空格。在清單 19 中我們嘗試使用帶有 -exec
的 find
, 而不是帶有 xargs
的 ls
。
清單 19. 對包含空格的文件名使用 find
和 -exec
|
到目前爲止,一切進展順利。但是不是缺少了什麼?哪個文件包含 grep
找到行?缺少了文件名,因爲 find
爲每個文件調用 grep
一次,而grep
非常智能,能夠知道您是不是僅提供文件名,您不需要它告訴您是哪個文件。
我們也可以改爲使用 xargs
,但我們已經看到了文件名中包含空格時出現的問題。我們還提到 find
可以生成一個以 null 分隔符分隔的文件名列表,這是 -print0
選項所起的作用。新的 find
可能使用加號(+)取代分號(;)作爲分隔符,這允許 find
在一次調用命令時傳遞儘可能多的名稱,類似於 xargs
。 在這種情況中,僅能使用 {} 一次,並且它必須是該命令的最後一個參數。清單 20 顯示了這兩種方法。
清單 20. 對包含空格的文件名使用 find
和 xargs
|
一般而言,兩種方法都是有效的,選擇哪種方法由您決定。記住,使用管道導出包含未受保護的空格的內容將導致問題,因此如果您要使用管道將輸出 導出到 xargs
,請使用將 -print0
選項和 find
結合使用,並使用 -0
選項告訴 xargs
接收使用 null 分隔符分隔的輸入。其他命令,包括 tar
,也支持使用 -0
選項並用 null 分隔符分隔的輸入,因此應該對支持該選項的命令使用它,除非您能確保您的輸入列表不會造成問題。
最後,我們介紹對文件列表進行操作。在執行刪除或重命名文件等重要操作之前,最好徹底地測試列表和仔細測試命令。進行良好的備份也是非常有價 值的。