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 容器,這樣運行速度會快很多。