xargs 命令也是管道命令中的一員。xargs命令的功能簡單來說就是引數代換。那麼什麼叫做引數代換,這裡首先要了解管道的概念。在 linux管道 命令一節中我們詳細介紹了管道命令的概念。這裡我們只是簡單進行一下說明。首先我們來看一下管道命令的流程圖
也就是管道前面的命令的輸出作為後面命令的標準輸入。既然是標準輸入,所以這裡就有一個要求是後面的命令可以在標準輸入中讀取資料。這個條件還是比較苛刻的,在linux中並不是所有的命令都可以在標準輸入裝置中讀取資料的,能讀取的命令數量不多,除了在前面介紹的 cut、grep、wc等命令之外,xargs也是一個可以在標準輸入中讀取資料的命令。xargs 在標準輸入中讀取出資料,然後將這些資料作為那些不能從標準輸入中讀取資料的命令的輸入。所以xargs命令,說白了,就是用來傳遞資料的。
下面我們舉個簡單的例子來看一下 xargs 命令的作用
$ echo php | ls
上面這個例子是想 用 ls 顯示 php 目錄下的內容,但是很遺憾,ls不是管道命令,不能從標準輸入裝置上讀取資料,所以它不會顯示 php 目錄下的內容。因為我們當前是在 workspace 目錄下面,所以說,上面的命令會顯示 workspace 目錄下的內容。
但是,如果我們使用 xargs 命令來做一個資料傳遞,那將會是另一種結果了
$ echo php | xargs ls
在我係統中,php目錄下的內容如下(可以列出php目錄下的內容了)
xargs命令語法
通過上面例子,可以看出,xargs命令的語法如下
$ xargs [-options] [command] xargs 後面的預設命令是echo 。
大多數的時候,xargs命令都是和管道一起使用的,不過,它也是可以單獨使用的。
輸入 xargs 按下回車以後,終端就開始等待使用者的輸入,並且將使用者的輸入作為標準輸入。我們可以輸入任意的內容,然後按下 ctrl+d 結束輸入。這是echo命令就會把我們輸入的內容顯示出來。
$ xargs find -name *.txt # 然後按 ctrl+d 結束輸入會顯示 jiyik.txt
xargs 引數舉例說明
從上面我們已經對xargs命令的語法有了簡單的瞭解,並且瞭解了它的基本使用方式。接下來我們對xargs命令的引數依次進行舉例說明
-d 引數與分隔符
預設情況下,xargs是使用空格作為分隔符將標準輸入裝置中的資料進行分割,並生成一個個命令的引數,例如
$ echo "dir1 dir2 dir3" | xargs mkdir
這樣會在當前目錄下生成三個資料夾
dir1 dir2 dir3
如果可以自定義分隔符,如下面使用冒號作為分隔符
$ echo "dir1:dir2:dir3" | xargs -d ":" mkdir
同樣也會生成三個資料夾 dir1 dir2 和 dir3。如果不使用選項 -d 指定分隔符的話,則只會生成一個資料夾 dir1:dir2:dir3
-p 確認要執行的命令
使用xargs命令之後,由於存在著引數轉換的過程,所以要對執行的命令進行確認。
-p 引數就是用來對要執行的命令進行確認的
$ echo "dir1 dir2 dir3" | xargs -p mkdir
執行之後會在終端顯示出要執行的命令,然後是讓使用者確認,輸入 y (大小寫均可)才會繼續執行命令。
-t 顯示要執行的命令
-t 選項是用來顯示要執行的命令的,和-p選項不同的是,它不需要使用者進行確認
$ echo "dir1 dir2 dir3" | xargs -t mkdir
會直接顯示
mkdir dir1 dir2 dir3
-L 指定行數
如果標準輸入中包含多行內容,那麼 -L 就可以指定多少行來作為下一個命令的引數,例如下面的示例
$ xargs find -name *.txt *.md find: 路徑必須在表示式之前: *.md
上面的命令同時將兩行的資料作為 find的引數導致報錯。
所以這種情況我們就可以使用 -L 選項來指定每一行作為一個引數,這樣就不會報錯了
$ xargs -L 1 find -name *txt jiyik.txt *md jiyik.md
-0 與find命令
由於xargs預設將空格作為分隔符,所以不太適合處理檔名,因為檔名可能包含空格。
find命令 有一個特別的引數 -print0,指定輸出的檔案列表以null分隔。然後,xargs命令的-0參數列示用null當作分隔符。
$ find /path -type f -print0 | xargs -0 rm
上面命令刪除/path路徑下的所有檔案。由於分隔符是null,所以處理包含空格的檔名,也不會報錯。
還有一個原因,使得xargs特別適合find命令。有些命令(比如rm)一旦引數過多會報"引數列表過長"的錯誤,從而而無法執行,改用xargs就沒有這個問題,因為它可以對每個引數執行一次命令。
$ find . -name "*.txt" | xargs grep "abc"
上面命令找出所有 TXT 檔案以後,對每個檔案搜尋一次是否包含字串abc。
-n 指定多少項
-L引數雖然解決了多行的問題,但是有時使用者會在同一行輸入多項。
$ xargs find -name "*.txt" "*.md" find: 路徑必須在表示式之前: *.md
上面的命令將同一行的兩項作為命令列引數,導致報錯。
-n引數指定每次將多少項,作為命令列引數。
$ xargs -n 1 find -name
上面命令指定將每一項(-n 1)標準輸入作為命令列引數,分別執行一次命令(find -name)。
-I 選項
如果xargs要將命令列引數傳給多個命令,可以使用-I引數。
-I 指定每一項命令列引數的替代字串。
$ cat jiyik.txt jiyik_one jiyik_two jiyik_three
$ cat jiyik.txt | xargs -I file sh -c 'echo file; mkdir file' jiyik_one jiyik_two jiyik_three
檢視當前目錄下已經生成了三個目錄
$ ls jiyik_one jiyik_three jiyik_two
上面程式碼中,jiyik.txt是一個包含三行的文字檔案。我們希望對每一項命令列引數,執行兩個命令(echo和mkdir),使用-I file表示file是命令列引數的替代字串。執行命令時,具體的引數會替代掉echo file; mkdir file裡面的兩個file。
--max-procs 引數
xargs預設只用一個程式執行命令。如果命令要執行多次,必須等上一次執行完,才能執行下一次。
--max-procs引數指定同時用多少個程式並行執行命令。--max-procs 2表示同時最多使用兩個程式,--max-procs 0表示不限制程式數。
$ docker ps -q | xargs -n 1 --max-procs 0 docker kill
上面命令表示,同時關閉儘可能多的 Docker 容器,這樣執行速度會快很多。