Linux經常使用命令--xargs

咱們能夠用管道將一個命令的stdout(標準輸出)重定向到另外一個命令的stdin(標準輸入),如:bash

$ cat foo.txt | grep "test"

解析:查看foo.txt文件並打印出含有test的行。命令行

可是有些命令只能以命令行參數的形式接受數據,而沒法經過stdin接受數據流。在這種狀況下,咱們無法用管道來提供哪些只有經過命令行參數才能提供的數據。code

那如今就該xargs上場了,它擅長將標準輸入數據轉換成命令行參數。字符串

預備知識:源碼

xargs命令應該緊跟在管道操做符以後,以標準輸入做爲主要的源數據流,它使用stdin並經過提供命令行參數來執行其餘命令。xargs命令把從stdin接收到的數據從新格式化,再將其做爲參數提供給其餘命令。it

1、將多行輸入轉換成單行輸出test

$ cat foo.txt  #  樣例文件
1 2 3 3 4 5
7 8 9 10
11 12

$ cat foo.txt | xargs
1 2 3 4 5 6 7 8 9 10 11 12

2、 將單行輸入轉換爲多行輸出擴展

$ cat foo.txt | xargs -n 3
1 2 3
4 5 6
7 8 9
10 11 12

解析:指定每行最大的參數數量n,將任何來自stdin的文本劃分紅多行,每行n個參數。file

xargs默認的定界符是空格,咱們本身能夠來設置定界符,用-d選項爲輸入指定一個定製的定界符。循環

$ echo "splitXsplitXsplitXsplit" | xargs -d X
split split split split

結合-n選項,咱們能夠將輸入劃分紅多行,每行包含兩個參數。

$ echo "splitXsplitXsplitXsplit" | xargs -d X -n 2
split split
split split

3、如何將參數傳遞給命令 讀取stdin(標準輸入),將格式化參數傳遞給命令

編寫一個小型的echo來更好的理解用xargs提供命令行參數的方法:

#!/bin/bash
#filename: cecho.sh

echo $@  "#"

當參數傳遞給cecho.sh後,它將會把這些參數打印出來,並以# 字符結尾

$ ./eceho.sh arg1 arg2
arg1 arg2 #

那麼,咱們如今想把這個命令執行屢次, 每次使用一個參數,難道咱們只能一遍一遍的執行?如今,咱們有一個名爲args.txt的參數列表文件,內容爲:

arg1
arg2
arg3

咱們來看下面的代碼

$ cat args.txt | xargs -n 1 ./cecho.sh
arg1 #
arg2 #
arg3 #

每次執行須要X個參數的命令時,使用:

$ cat args.txt | xargs -n 2 ./cecho.sh
arg1 arg2 #
arg3 #

可是有些時候,咱們須要一些不變的參數,看下面這種命令格式:

$ ./cecho -p arg1 -1

在上面的命令執行過程當中,arg1 是惟一可變的參數,其他部分都保持不變,咱們能夠從文件(argx.txt)中讀取參數,按照下面的方式提供給命令:

./cecho -p arg1 -1
./cecho -p arg2 -1
./cecho -p arg3 -1

xargs有個一個-I(大寫的i)的選項,能夠提供上面這種形式的命令執行序列。咱們用-I指定替換字符串,這個字符串在xargs擴展(傳遞給命令)時會被替換掉。若是將-I與xargs結合使用,對於每個參數,命令都會被執行一次。

$ cat args.txt | xargs -I {} ./cecho -p {} -1

-p arg1 -1 #

-p arg2 -1 # 

-p arg3 -1 #

-I {}指定了替換字符串。對於每個命令參數,字符串{}都會被從stdin讀取到的參數所替換掉。使用-I的時候,命令會以循環的方式執行。若是有3個參數,那個命令就會被執行3次。在每一次執行的時候{}都會被替換爲相應的參數。

xargs常常會與find一塊兒使用,不過人們一般都會以一種錯誤的方式去使用它們。

$ find . type -f -name "*.txt" -print | xargs rm -f {} \;

咱們無法預測find命令輸出的結果的定界符是什麼('\n'或' ')。不少文件都有可能包含空格符(' '),所以xargs極可能會誤認爲它們是定界符(例如:hell text.txt會被xargs理解爲hello和text.txt兩個文件)。

只要咱們把find的輸出做爲xargs的輸入,就必須將-print0與find結合使用,以字符null('\0')來分隔輸出。

用find匹配並列出全部的.txt文件,而後用xargs將這些文件刪除:

$ find . -type f -name "*.txt" -print0 | xargs -0 rm -f {} \;

這樣就能夠刪除全部的.txt文件,xargs -0將\0做爲輸入的定界符。

統計源碼目錄下全部.sh的文件行數。

$ find . type f -name "*.sh" -print0 | xargs -0 wc -l
相關文章
相關標籤/搜索