天天看點

xargs指令用法

大多數 Linux 指令都會産生輸出:檔案清單、字元串清單等。但如果要使用其他某個指令并将前一個指令的輸出作為參數該怎麼辦?例如,file 指令顯示檔案類型(可執行檔案、ascii 文本等);您可以處理輸出,使其僅顯示檔案名,現在您希望将這些名稱傳遞給 ls -l 指令以檢視時間戳記。xargs 指令就是用來完成此項工作的。它允許您對輸出執行其他某些指令。

xargs – build and execute command lines from standard input

在使用find指令的-exec選項處理比對到的檔案時, find指令将所有比對到的檔案一起傳遞給exec執行。但有些系統對能夠傳遞給exec的指令長度有限制,這樣在find指令運作幾分鐘之後,就會出現溢出錯誤。錯誤資訊通常是“參數列太長”或“參數列溢出”。這就是xargs指令的用處所在,特别是與find指令一起使用。

記住下面這個來自于第 1 部分中的文法:

file -Lz * | grep ASCII | cut -d”:” -f1 | xargs ls -ltr

讓我們來剖析這個指令字元串。第一個,file -Lz *,用于查找是符号連結或者經過壓縮的檔案。它将輸出傳遞給下一個指令 grep ASCII,該指令在其中搜尋 “ASCII” 字元串并産生如下所示的輸出:

alert_DBA102.log: ASCII English text

alert_DBA102.log.Z: ASCII text (compress’d data 16 bits)

dba102_asmb_12307.trc.Z: ASCII English text (compress’d data 16 bits)

dba102_asmb_20653.trc.Z: ASCII English text (compress’d data 16 bits)

由于我們隻對檔案名感興趣,是以我們應用下一個指令 cut -d”:” -f1,僅顯示第一個字段:

alert_DBA102.log

alert_DBA102.log.Z

dba102_asmb_12307.trc.Z

dba102_asmb_20653.trc.Z

現在,我們希望使用 ls -l 指令,将上述清單作為參數進行傳遞,一次傳遞一個。xargs 指令允許您這樣做。最後一部分,xargs ls -ltr,用于接收輸出并對其執行 ls -ltr 指令,如下所示:

ls -ltr alert_DBA102.log

ls -ltr alert_DBA102.log.Z

ls -ltr dba102_asmb_12307.trc.Z

ls -ltr dba102_asmb_20653.trc.Z

是以,xargs 本身雖然沒有多大用處,但在與其他指令相結合時,它的功能非常強大。

下面是另一個示例,我們希望計算這些檔案中的行數:

$ file * | grep ASCII | cut -d”:” -f1 | xargs wc -l

47853 alert_DBA102.log

19 dba102_cjq0_14493.trc

29053 dba102_mmnl_14497.trc

154 dba102_reco_14491.trc

43 dba102_rvwr_14518.trc

77122 total

(注:上述任務還可用以下指令完成:)

$ wc -l ‘file * | grep ASCII | cut -d”:” -f1 | grep ASCII | cut -d”:” -f1‘

該 xargs 版本用于闡釋概念。Linux 可以用幾種方法來完成同一個任務;請使用最适合您的情況的方法。

使用該方法,您可以快速重命名目錄中的檔案。

$ ls | xargs -t -i mv {} {}.bak

-i 選項告訴 xargs 用每項的名稱替換 {}。-t 選項訓示 xargs 先列印指令,然後再執行。

另一個非常有用的操作是當您使用 vi 打開要編輯的檔案時:

$ file * | grep ASCII | cut -d”:” -f1 | xargs vi

該指令使用 vi 逐個打開檔案。當您希望搜尋多個檔案并打開它們進行編輯時,使用該指令非常友善。

它還有幾個選項。最有用的可能是 -p 選項,它使操作具有可互動性:

$ file * | grep ASCII | cut -d”:” -f1 | xargs -p vi

vi alert_DBA102.log dba102_cjq0_14493.trc dba102_mmnl_14497.trc dba102_reco_14491.trc dba102_rvwr_14518.trc ?…

此處的 xarg 要求您在運作每個指令之前進行确認。如果您按下 “y”,則執行指令。當您對檔案進行某些可能有破壞且不可恢複的操作(如删除或覆寫)時,您會發現該選項非常有用。

-t 選項使用一個詳細模式;它顯示要運作的指令,是調試過程中一個非常有幫助的選項。

如果傳遞給 xargs 的輸出為空怎麼辦?考慮以下指令:

$ file * | grep SSSSSS | cut -d”:” -f1 | xargs -t wc -l

wc -l

$

在此處,搜尋 “SSSSSS” 後沒有比對的内容;是以 xargs 的輸入均為空,如第二行所示(由于我們使用 -t 這個詳細選項而産生的結果)。雖然這可能會有所幫助,但在某些情況下,如果沒有要處理的内容,您可能希望停止 xargs;如果是這樣,可以使用 -r 選項:

$ file * | grep SSSSSS | cut -d”:” -f1 | xargs -t -r wc -l

$

如果沒有要運作的内容,該指令退出。

假設您希望使用 rm 指令(該指令将作為 xargs 指令的參數)删除檔案。然而,rm 隻能接受有限數量的參數。如果您的參數清單超出該限制怎麼辦?xargs 的 -n 選項限制單個指令行的參數個數。

下面顯示了如何限制每個指令行僅使用兩個參數:即使向 xargs ls -ltr 傳遞五個檔案,但每次向 ls -ltr 僅傳遞兩個檔案。

$ file * | grep ASCII | cut -d”:” -f1 | xargs -t -n2 ls -ltr

ls -ltr alert_DBA102.log dba102_cjq0_14493.trc

-rw-r—– 1 oracle dba 738 Aug 10 19:18 dba102_cjq0_14493.trc

-rw-r–r– 1 oracle dba 2410225 Aug 13 05:31 alert_DBA102.log

ls -ltr dba102_mmnl_14497.trc dba102_reco_14491.trc

-rw-r—– 1 oracle dba 5386163 Aug 10 17:55 dba102_mmnl_14497.trc

-rw-r—– 1 oracle dba 6808 Aug 13 05:21 dba102_reco_14491.trc

ls -ltr dba102_rvwr_14518.trc

-rw-r—– 1 oracle dba 2087 Aug 10 04:30 dba102_rvwr_14518.trc

使用該方法,您可以快速重命名目錄中的檔案。

$ ls | xargs -t -i mv {} {}.bak

-i 選項告訴 xargs 用每項的名稱替換 {}。

我需要将一個用.svn管理的項目改成由CVS來管理,是以,在導入整個項目到CVS中之前,我需要删除所有目錄下以及子孫目錄下的.svn目錄及.svn目錄下的的子目錄和檔案。我一直尋找一種最簡單的方法,最後寫了一個程式去幹這事情。結果同僚告訴我隻需要一條指令就可以了:find -name ‘.svn’ |xargs rm -rf

這個教訓非常慘重,我一生讨厭傻瓜,可那一刻發現自己是最大的傻瓜!

是的,雖然我們——至少是我,天天使用LINUX但是真的是在高效的使用這個系統嗎?不,很多時候并沒有花時間去研究它,使用一些固有愚蠢的方式和思維模式在使用這個系統。

1. 建立多級目錄:

mkidr 指令用來建立目錄,事實上,我們一直都是這麼幹的。但是在這麼使用的時候我們并沒有去看它的那些參數提供了哪些額外的功能.

mkidr -p /share/dragon ; 在根目錄下建立share目錄,并在/share目錄下建立dragon目錄。mkdir -p guicmd/{bin,lib,src,share/version,doc/{html,pdf,info,man}}

;用來建立一個複雜的項目目錄樹。

2.find 配合xargs使用:

find -name ‘.svn’ |xargs rm -rf ;這個不用說了,就是我前面提到的。

xargs更加象一個篩選器,将符合管道傳遞過來的檔案名的内容一并處理掉,這是一個極度高效的方法。