'淺談Linux中的xargs命令'

Linux Redis AWK 簡書 Cloudera IT運維社區 2019-08-27
"

在說xargs命令之前,先說兩句Linux中的管道(pipe)。

管道負責單向連接前一個程序的標準輸出與後一個程序的標準輸入,其本質是一個共享文件。我們日常最常用到的管道是匿名管道,Shell中的管道符號為“|”。

"

在說xargs命令之前,先說兩句Linux中的管道(pipe)。

管道負責單向連接前一個程序的標準輸出與後一個程序的標準輸入,其本質是一個共享文件。我們日常最常用到的管道是匿名管道,Shell中的管道符號為“|”。

淺談Linux中的xargs命令

有空會讀讀與管道有關的內核源碼的,比如pipe()

管道用法舉例:

  • 打印/usr/lib目錄下的內容,按大小排序,並分頁顯示行號
ll -Sh /usr/lib | less -N
  • 取出歷史登錄信息中的用戶名,排序、去重並計數
last | cut -d ' ' -f 1 | sort | uniq -c
  • 殺掉所有正在運行的redis-cli進程
kill -15 `ps aux | grep redis-cli | grep -v grep | awk '{print $2}'`

那麼xargs命令又和管道有什麼關係呢?如果把上面的第三個例子換一種寫法:

"

在說xargs命令之前,先說兩句Linux中的管道(pipe)。

管道負責單向連接前一個程序的標準輸出與後一個程序的標準輸入,其本質是一個共享文件。我們日常最常用到的管道是匿名管道,Shell中的管道符號為“|”。

淺談Linux中的xargs命令

有空會讀讀與管道有關的內核源碼的,比如pipe()

管道用法舉例:

  • 打印/usr/lib目錄下的內容,按大小排序,並分頁顯示行號
ll -Sh /usr/lib | less -N
  • 取出歷史登錄信息中的用戶名,排序、去重並計數
last | cut -d ' ' -f 1 | sort | uniq -c
  • 殺掉所有正在運行的redis-cli進程
kill -15 `ps aux | grep redis-cli | grep -v grep | awk '{print $2}'`

那麼xargs命令又和管道有什麼關係呢?如果把上面的第三個例子換一種寫法:

淺談Linux中的xargs命令

這說明kill命令沒有接收到應有的參數。還有很多命令(比如最常見的mkdir、rm、cp等等等)都不會從標準輸入讀取內容,這時如果在管道符後加上xargs,再加上要執行的命令,那麼前一個程序的標準輸出就會作為後一個程序的參數,而不是標準輸入了。

"

在說xargs命令之前,先說兩句Linux中的管道(pipe)。

管道負責單向連接前一個程序的標準輸出與後一個程序的標準輸入,其本質是一個共享文件。我們日常最常用到的管道是匿名管道,Shell中的管道符號為“|”。

淺談Linux中的xargs命令

有空會讀讀與管道有關的內核源碼的,比如pipe()

管道用法舉例:

  • 打印/usr/lib目錄下的內容,按大小排序,並分頁顯示行號
ll -Sh /usr/lib | less -N
  • 取出歷史登錄信息中的用戶名,排序、去重並計數
last | cut -d ' ' -f 1 | sort | uniq -c
  • 殺掉所有正在運行的redis-cli進程
kill -15 `ps aux | grep redis-cli | grep -v grep | awk '{print $2}'`

那麼xargs命令又和管道有什麼關係呢?如果把上面的第三個例子換一種寫法:

淺談Linux中的xargs命令

這說明kill命令沒有接收到應有的參數。還有很多命令(比如最常見的mkdir、rm、cp等等等)都不會從標準輸入讀取內容,這時如果在管道符後加上xargs,再加上要執行的命令,那麼前一個程序的標準輸出就會作為後一個程序的參數,而不是標準輸入了。

淺談Linux中的xargs命令

Dash軟件中xargs命令的man page

看官可以嘗試執行以下兩對命令,看看輸出有什麼不同,能夠加深理解:

  • echo '--help' | cat與echo '--help' | xargs cat
  • 隨便找一個Spring項目的代碼目錄,分別執行find . -name '*.java' | grep Impl與find . -name '*.java' | xargs grep Impl

同樣地,上面例子中的kill命令應該改寫成:

ps aux | grep redis-cli | grep -v grep | awk '{print $2}' | xargs kill -15

xargs命令本身也有一些參數,使用方法很靈活,下面再舉幾個例子。

  • 自定義分隔符
  • xargs默認用IFS(inner field separator,即內部域分隔符,包含空格、製表符、換行符)分割上一個程序的標準輸出。如果要用其他分隔符,可以用-d參數,例如:
~ echo '1,2,3,4,5' | xargs -d ',' echo
1 2 3 4 5

特別地,用-0(注意是數字0)參數可以指定NULL字符'\\0'作為分隔符。

  • 分批傳參
  • 用-n參數可以規定每次傳遞多少個參數給後面的命令,它可以單用,也可以與-d配合使用,例如:
~ echo '1,2,3,4,5,6,7,8,9' | xargs -d ',' -n 4 echo
1 2 3 4
5 6 7 8
9
  • 指定終止符
  • 用-E參數可以指定xargs在遇到哪個字符串時停止解析(不含該字符串)。-E不能與-d同用,例如:
~ echo 'cd pwd ls ps' | xargs -E 'ls' echo
cd pwd
  • 交互式執行
  • 用-p參數就會在每次執行命令之前詢問,輸入y(yes)才會真正執行。如果只是想觀察命令本身,可以用-t參數。例如:
~ echo '1,2,3,4,5,6,7,8,9' | xargs -d ',' -n 4 -t echo
echo 1 2 3 4
1 2 3 4
echo 5 6 7 8
5 6 7 8
echo 9
9
  • 指定替換參數位置
  • xargs接收的參數默認會分配到下一個命令的結尾,即追加。如果想要指定替換的參數位置,可以用-I或者-i參數。其中,-i固定用雙大括號{}作為佔位符,-I則可以自行指定其他符號作為佔位符。這個東西很有用,例如:
# 計算表達式的值
~ echo '77' | xargs -I 'q' expr 2 \\* q + 8
162
# 批量重命名目錄下的文件
~ ls | xargs -i mv {} {}.bak
# 批量複製目錄下的文件
~ find . -name "*.jar" | xargs -i cp {} /opt/cloudera/jars

mv、cp等命令對參數列表的長度有限制,如果按普通方法一次操作太多文件,會報“Argument list too long”錯誤。而xargs每次傳參時是以默認128KB的批次進行,所以一切正常。批次大小還可以用-s參數自行指定。

作者:LittleMagic

鏈接:https://www.jianshu.com/p/0aa07a901825

來源:簡書

簡書著作權歸作者所有,任何形式的轉載都請聯繫作者獲得授權並註明出處。

"

相關推薦

推薦中...