Linux-xargs命令

forest7707發表於2017-05-17

Linux-xargs命令


http://blog.csdn.net/yangshangwei/article/details/52666202

xargs是給命令傳遞引數的一個過濾器,也是組合多個命令的一個工具。它把一個資料流分割為一些足夠小的塊,以方便過濾器和命令進行處理。通常情況下,xargs從管道或者stdin中讀取資料,但是它也能夠從檔案的輸出中讀取資料。xargs的預設命令是echo,這意味著透過管道傳遞給xargs的輸入將會包含換行和空白,不過透過xargs的處理,換行和空白將被空格取代。

該命令的主要功能是從輸入中構建和執行shell命令。       

    在使用find命令的-exec選項處理匹配到的檔案時, find命令將所有匹配到的檔案一起傳遞給exec執行。但有些系統對能夠傳遞給exec的命令長度有限制,這樣在find命令執行幾分鐘之後,就會出現溢位錯誤。錯誤資訊通常是“引數列太長”或“引數列溢位”。這就是xargs命令的用處所在,特別是與find命令一起使用。  
    find命令把匹配到的檔案傳遞給xargs命令,而xargs命令每次只獲取一部分檔案而不是全部,不像-exec選項那樣。這樣它可以先處理最先獲取的一部分檔案,然後是下一批,並如此繼續下去。  
    在有些系統中,使用-exec選項會為處理每一個匹配到的檔案而發起一個相應的程式,並非將匹配到的檔案全部作為引數一次執行;這樣在有些情況下就會出現程式過多,系統效能下降的問題,因而效率不高;  
    而使用xargs命令則只有一個程式。另外,在使用xargs命令時,究竟是一次獲取所有的引數,還是分批取得引數,以及每一次獲取引數的數目都會根據該命令的選項及系統核心中相應的可調引數來確定。

下面我們來看看xargs有哪些引數可以選擇.

options

  • -a file
    : 從file中讀入資料

    $cat 1.txt aaa bbb ccc ddd a b $xargs -a 1.txt aaa bbb ccc ddd a b
  • -0
    : 當輸入有特殊字元時,將其當作一般字元處理,比如""和空格

    $echo "// " | xargs // $echo "// " | xargs -0 //  
  • -d
    : 指定分隔符

    $cat 1.txt
    aaa bbb ccc ddd
    a b $cat 1.txt | xargs -d 'c' aaa bbb     ddd
    a b
     
  • -E eof-str
    : 指定結束標誌為eof-str,xargs處理到這個標誌就會停止

    $xargs -E 'ddd' -a 1.txt
    aaa bbb ccc $xargs -E 'dd' -a 1.txt
    aaa bbb ccc ddd a b $cat 1.txt | xargs -E 'ddd' aaa bbb ccc
  • -I replace-str
    : 將每行輸入輸入內容替換為replace-str

    $cat 1.txt
    aaa bbb ccc ddd
    a b $cat 1.txt | xargs -t -I {} echo {} >> 1.txt echo aaa bbb ccc ddd echo a b $cat 1.txt
    aaa bbb ccc ddd
    a b
    aaa bbb ccc ddd
    a b
  • -i
    : 等同於-I{}

    $cat 1.txt
    aaa bbb ccc ddd
    a b $cat 1.txt | xargs -t -i echo {} >> 1.txt echo aaa bbb ccc ddd echo a b $cat 1.txt
    aaa bbb ccc ddd
    a b
    aaa bbb ccc ddd
    a b
  • -L max-lines
    : 每次讀取max-line行輸入交由xargs處理

    $cat 1.txt
    aaa bbb ccc ddd
    a b $cat 1.txt |xargs -L 2
    aaa bbb ccc ddd a b $cat 1.txt |xargs -L 1
    aaa bbb ccc ddd
    a b
  • -l
    : 類似於-L,區別在於-l可以不指定引數,預設為1.

  • -n max-args
    : 每行執行max-args個輸入,預設執行所有

    $cat 1.txt | xargs -n 2 
    aaa bbb
    ccc ddd
    a b
  • -p
    : 互動模式,執行前詢問是否執行

    $cat 1.txt | xargs -p
    /bin/echo aaa bbb ccc ddd a b ?...y
    aaa bbb ccc ddd a b $cat 1.txt | xargs -p
    /bin/echo aaa bbb ccc ddd a b ?...n
  • -r
    : 無輸入則停止執行,預設至少執行1次

    $ echo ""|xargs -t mv
    mv mv: missing file operand
    Try `mv --help` for more information.
    $ echo ""|xargs -t -r mv    #直接退出
  • -s max-chars
    : xargs每次執行命令的最大長度(含空格)

    $ cat 1.txt
    aaa bbb ccc ddd a b
    $ cat 1.txt |xargs -t -s 30 /bin/echo aaa bbb ccc ddd a b 
    aaa bbb ccc ddd a b #length(/bin/echo aaa bbb ccc ddd a b )=30 $cat 1.txt |xargs -t -s 14 /bin/echo aaa 
    aaa
    /bin/echo bbb 
    bbb
    /bin/echo ccc 
    ccc
    /bin/echo ddd 
    ddd
    /bin/echo a b 
    a b #length(/bin/echo aaa )=14
  • -t
    : 先列印執行的命令,然後執行

    $cat 1.txt | xargs -t
    /bin/echo aaa bbb ccc ddd a b
    aaa bbb ccc ddd a b
  • -x
    : 當xargs執行的命令長度大於-s max-char時,停止執行

  • -P max-procs
    : 修改執行緒數,預設為單執行緒.max-procs為0時,as many processes as possible

              /> ls -l
    -rw-r--r--. 1 root root        0 Nov 12 10:02 datafile3
    -rw-r--r--. 1 root root 10530 Nov 11 23:08 test.tar.bz2
    -rwxr--r--. 1 root root    183 Nov 11 08:02 users
    -rw-r--r--. 1 root root    279 Nov 11 08:45 users2
    #查詢當前目錄下的每一個普通檔案,然後使用xargs命令來測試它們分別屬於哪類檔案。

    /> find . -type f -print | xargs file
    ./users2:        ASCII text
    ./datafile3:      empty
    ./users:          ASCII text
    ./test.tar.bz2: bzip2 compressed data, block size = 900k
    #回收當前目錄下所有普通檔案的執行許可權。

    /> find . -type f -print | xargs chmod a-x
    /> ls -l
    -rw-r--r--. 1 root root     0 Nov 12 10:02 datafile3
    -rw-r--r--. 1 root root 10530 Nov 11 23:08 test.tar.bz2
    -rw-r--r--. 1 root root   183 Nov 11 08:02 users
    -rw-r--r--. 1 root root   279 Nov 11 08:45 users2
    #在當面目錄下查詢所有普通檔案,並用grep命令在搜尋到的檔案中查詢hostname這個詞

    /> find . -type f -print | xargs grep "hostname"
    #在整個系統中查詢記憶體資訊轉儲檔案(core dump) ,然後把結果儲存到/tmp/core.log 檔案中。

    /> find / -name "core" -print | xargs echo "" >/tmp/core.log       /> pgrep mysql | xargs kill -9  #直接殺掉mysql的程式
    
[1]+  Killed                  mysql

例子如下:
1. 當你嘗試用rm 刪除太多的檔案,你可能得到一個錯誤資訊:/bin/rm Argument list too long. 用xargs 去避免這個問題
find ~ -name ‘*.log' -print0 | xargs -0 rm -f

2. 獲得/etc/ 下所有*.conf 結尾的檔案列表,有幾種不同的方法能得到相同的結果,下面的例子僅僅是示範怎麼實用xargs ,在這個例子中實用 xargs將find 命令的輸出傳遞給ls -l
# find /etc -name "*.conf" | xargs ls –l

3. 假如你有一個檔案包含了很多你希望下載的URL, 你能夠使用xargs 下載所有連結
# cat url-list.txt | xargs wget –c

4. 查詢所有的jpg 檔案,並且壓縮它
# find / -name *.jpg -type f -print | xargs tar -cvzf images.tar.gz

5. 複製所有的圖片檔案到一個外部的硬碟驅動
# ls *.jpg | xargs -n1 -i cp {} /external-hard-drive/directory

EXAMPLES
find /tmp -name core -type f -print | xargs /bin/rm -f
Find files named core in or below the directory /tmp and delete them. Note that this will work incorrectly if there are any filenames containing newlines or spaces.

find /tmp -name core -type f -print0 | xargs -0 /bin/rm -f
Find files named core in or below the directory /tmp and delete them, processing filenames in such a way that file or directory names containing spaces or newlines are correctly handled.

find /tmp -depth -name core -type f -delete
Find files named core in or below the directory /tmp and delete them, but more efficiently than in the previous example (because we avoid the need to use fork(2) and exec(2) to launch rm and we don't need the extra xargs process).

cut -d: -f1 < /etc/passwd | sort | xargs echo
Generates a compact listing of all the users on the system.

xargs sh -c 'emacs "$@" < /dev/tty' emacs
Launches the minimum number of copies of Emacs needed, one after the other, to edit the files listed on xargs' standard input. This example achieves the same effect as BSD's -o option, but in a more flexible and portable way.

例如:
如果path目錄下檔案過多就會因為“引數列表過長”而報錯無法執行。但改用xargs以後,問題即獲解決。
find /path -type f -print0 | xargs -0 rm

xargs將find產生的長串檔案列表拆散成多個子串,然後對每個子串呼叫rm。-print0表示輸出以null分隔(-print使用換行);-0表示輸入以null分隔。這樣要比如下使用find命令效率高的多。
find /path -type f -exec rm '{}' \;

xargs命令應該緊跟在管道運算子之後,它以標準輸入作為主要的源資料流,並使用stdin並透過提供命令列引數來執行其他命令,例如:
command | xargs

例項應用1,將多行輸入轉換為單行輸出:
amosli@amosli-pc:~/learn$ cat example.txt
1 2 3 4 5
6 7
8
amosli@amosli-pc:~/learn$ cat example.txt | xargs
1 2 3 4 5 6 7 8

例項應用2,將單行輸入轉換為多行輸出:
amosli@amosli-pc:~/learn$ cat example.txt | xargs -n 2
1 2
3 4
5 6
7 8

空格是預設的定界符,-n 表示每行顯示幾個引數

還可以使用-d引數來分隔引數,如下:
amosli@amosli-pc:~/learn$ echo "splitXhiXamosliXsplit" | xargs -d "X" -n 1
split
hi
amosli
split

例項應用3,讀取stdin,將格式化引數傳遞給命令
#定義一個echo命令每次在輸出引數後都加上#
amosli@amosli-pc:~/learn$ cat cecho.sh
echo $*'#'

#需求1:輸出多個引數
amosli@amosli-pc:~/learn$ sh cecho.sh arg1
arg1#
amosli@amosli-pc:~/learn$ sh cecho.sh arg2
arg2#
amosli@amosli-pc:~/learn$ sh cecho.sh arg3
arg3#

#需求2:一次性提供所有的命令引數
amosli@amosli-pc:~/learn$ sh cecho.sh arg1 arg2 arg3
arg1 arg1 arg2 arg3#

#針對需求1、2,使用xargs代替,先用vi建一個新檔案args.txt,如下:
amosli@amosli-pc:~/learn$ cat args.txt
arg1
arg2
arg3
#批次輸出引數:
amosli@amosli-pc:~/learn$ cat args.txt | xargs -n 1
arg1
arg2
arg3
amosli@amosli-pc:~/learn$ cat args.txt | xargs -n 2 sh cecho.sh
arg1 arg2#
arg3#
#一次性輸出所有引數:
amosli@amosli-pc:~/learn$ cat args.txt | xargs sh cecho.sh ;
arg1 arg2 arg3#

需求3,如何將引數嵌入到固定的命令列中?如下所示:
amosli@amosli-pc:~/learn$ sh cecho.sh -p args1 -1
-p args1 -1#
amosli@amosli-pc:~/learn$ sh cecho.sh -p args2 -1
-p args2 -1#
amosli@amosli-pc:~/learn$ sh cecho.sh -p args3 -1
-p args3 -1#

使用xargs的解決方案:
amosli@amosli-pc:~/learn$ cat args.txt | xargs -I {} sh cecho.sh -p {} -1
-p arg1 -1#
-p arg2 -1#
-p arg3 -1#

#-I {}批定了替換字串,字串{}會被從stdin讀取到的引數所替換,使用-I時,能迴圈按要求替換相應的引數

例項應用4,結合find使用xargs
前面已經舉過例子,這裡要注意的是檔名稱定界符要以字元null來分隔輸出,如下所示,否則可能會誤刪檔案
amosli@amosli-pc:~/learn$ find . -type f -name "*test*.txt" -print0 | xargs -0 rm -f

其他:
cat file | ( while read arg; do cat $arg; done )
cat file | xargs -I {} cat {}

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/21220384/viewspace-2139199/,如需轉載,請註明出處,否則將追究法律責任。

相關文章