Linux 引數代換 命令 xargs

跡憶客 發表於 2021-12-07
Linux

xargs 命令也是管道命令中的一員。xargs命令的功能簡單來說就是引數代換。那麼什麼叫做引數代換,這裡首先要了解管道的概念。在 linux管道 命令一節中我們詳細介紹了管道命令的概念。這裡我們只是簡單進行一下說明。首先我們來看一下管道命令的流程圖

 

Linux 引數代換 命令 xargs

 

 

也就是管道前面的命令的輸出作為後面命令的標準輸入。既然是標準輸入,所以這裡就有一個要求是後面的命令可以在標準輸入中讀取資料。這個條件還是比較苛刻的,在linux中並不是所有的命令都可以在標準輸入裝置中讀取資料的,能讀取的命令數量不多,除了在前面介紹的 cut、grep、wc等命令之外,xargs也是一個可以在標準輸入中讀取資料的命令。xargs 在標準輸入中讀取出資料,然後將這些資料作為那些不能從標準輸入中讀取資料的命令的輸入。所以xargs命令,說白了,就是用來傳遞資料的。

下面我們舉個簡單的例子來看一下 xargs 命令的作用

$ echo php | ls

 

上面這個例子是想 用 ls 顯示 php 目錄下的內容,但是很遺憾,ls不是管道命令,不能從標準輸入裝置上讀取資料,所以它不會顯示 php 目錄下的內容。因為我們當前是在 workspace 目錄下面,所以說,上面的命令會顯示 workspace 目錄下的內容。

但是,如果我們使用 xargs 命令來做一個資料傳遞,那將會是另一種結果了

$ echo php | xargs ls

 

在我係統中,php目錄下的內容如下(可以列出php目錄下的內容了)

 

 

Linux 引數代換 命令 xargs

 

 

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 (大小寫均可)才會繼續執行命令。

 

Linux 引數代換 命令 xargs

 

 

-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。

 

Linux 引數代換 命令 xargs

 

 

--max-procs 引數

xargs預設只用一個程式執行命令。如果命令要執行多次,必須等上一次執行完,才能執行下一次。

--max-procs引數指定同時用多少個程式並行執行命令。--max-procs 2表示同時最多使用兩個程式,--max-procs 0表示不限制程式數。

$ docker ps -q | xargs -n 1 --max-procs 0 docker kill

上面命令表示,同時關閉儘可能多的 Docker 容器,這樣執行速度會快很多。