xargs 指令:用法、-n 與 -I 選項,以及搭配 find 使用
xargs 指令是把從標準輸入收到的行與字詞轉成另一個指令的引數並執行的 Linux 工具。我們在 AlmaLinux 9 伺服器的工作資料夾中,把 find 找到的三個記錄檔透過 xargs 交給 wc,結果檔名含空格的一個檔案被拆成兩個而發生錯誤;加上 -print0 與 -0 後,三個檔案的行數都顯示出來了。
以下輸出是在 AlmaLinux 9.8 伺服器上以 root 帳號於工作資料夾內執行的結果。名稱清單、記錄檔和暫存檔是為測試建立的範例檔案,其中的 IP 位址和工作資料夾路徑也是範例值。
1️⃣ xargs 指令基本用法
xargs 把前一個指令傳來的標準輸入依空格和換行切開,放到後面所寫指令的引數位置再執行。我們用每行一個名稱的 names.txt 確認。
cat names.txtalice
bob
carol
dave
erin把 cat 的輸出交給 xargs echo,五行會成為 echo 一次的引數,顯示成一行。
cat names.txt | xargs echoalice bob carol dave erin後面不寫指令時,xargs 會執行 echo,所以結果相同。
cat names.txt | xargsalice bob carol dave erin管線是把前一個指令的輸出接到後一個指令標準輸入的通道,因此後一個指令的引數位置什麼也沒有。把含有三個檔名的 list.txt 只用管線交給 wc -l,wc 會計算清單本身的 3 行。
cat list.txtlogs/access.log
logs/error.log
tmp/keep.txtcat list.txt | wc -l3中間放入 xargs,清單裡的三個名稱就成為 wc 的引數,顯示每個檔案的行數。
cat list.txt | xargs wc -l 3 logs/access.log
2 logs/error.log
1 tmp/keep.txt
6 total2️⃣ xargs -n 與 -I 選項
沒有選項時,所有輸入都進入一次指令,因此要重複執行指令,就用 -n 決定每次傳遞的引數數量。下圖可確認相同的五個名稱如何依選項分組。
-n 1 對每個名稱執行 echo,輸出五行。
cat names.txt | xargs -n 1 echoalice
bob
carol
dave
erin-n 2 每兩個一組,剩下的一個另外傳遞。
cat names.txt | xargs -n 2 echoalice bob
carol dave
erin要親眼確認執行的指令,就加上 -t。指令行會先出現,下面接著輸出。
cat names.txt | xargs -t -n 2 echoecho alice bob
alice bob
echo carol dave
carol dave
echo erin
erin引數必須放在指令結尾以外的位置時,就用 -I 指定佔位字元。{} 的位置每次放入一行,同樣的文字出現多次時會全部替換。
cat names.txt | xargs -I {} echo 'user: {}'user: alice
user: bob
user: carol
user: dave
user: erincat names.txt | xargs -I {} echo '{} -> home/{}'alice -> home/alice
bob -> home/bob
carol -> home/carol
dave -> home/dave
erin -> home/erin同樣的方式可依名稱建立資料夾。先建立 home 資料夾,再用 -I {} 在其下建立各名稱的資料夾,就會產生五個資料夾。
mkdir homecat names.txt | xargs -I {} mkdir home/{}ls homealice bob carol dave erin-I 把一行當成一個引數,因此不能和 -n 一起使用。兩者同時寫時,-I 會連同警告被忽略,{} 照字面輸出。
cat names.txt | xargs -I {} -n 2 echo {}xargs: warning: options --replace and --max-args/-n are mutually exclusive, ignoring previous --replace value
{} alice bob
{} carol dave
{} erin-L 依行數分組。一行有多個字詞時,該行的字詞會一起傳遞,在每行只有一個名稱的 names.txt 中,-L 2 的結果和 -n 2 相同。
cat names.txt | xargs -L 2 echoalice bob
carol dave
erin3️⃣ find 與 xargs 組合
不必手動建立名稱清單,也能把 find 找到的檔案清單直接交給 xargs。在記錄檔資料夾尋找以 .log 結尾的檔案會找到三個,其中一個名稱含空格。
find /root/work/logs -name '*.log'/root/work/logs/access.log
/root/work/logs/error.log
/root/work/logs/old access.log把這份清單直接交給 xargs wc -l,含空格的名稱被拆成 old 和 access.log,出現兩行錯誤,合計也只算了兩個檔案的 5 行。
find /root/work/logs -name '*.log' | xargs wc -l 3 /root/work/logs/access.log
2 /root/work/logs/error.log
wc: /root/work/logs/old: No such file or directory
wc: access.log: No such file or directory
5 totalfind 的 -print0 以空字元而非換行分隔名稱,xargs 的 -0 只以該空字元切分引數。兩者一起使用,連含空格的檔案在內,三個檔案的行數都會顯示。
find /root/work/logs -name '*.log' -print0 | xargs -0 wc -l 3 /root/work/logs/access.log
2 /root/work/logs/error.log
1 /root/work/logs/old access.log
6 totalfind 的 -exec 選項也能做到同樣的事。在 {} 後加上 + 會一次傳遞找到的檔案,所以結果相同,檔名中的空格也由 find 原樣傳遞。xargs 也能接收 find 以外指令的輸出,因此輸入不只來自 find 時使用,需要決定每次傳遞數量(-n)或同時執行數(-P)時也使用 xargs。
find /root/work/logs -name '*.log' -exec wc -l {} + 3 /root/work/logs/access.log
2 /root/work/logs/error.log
1 /root/work/logs/old access.log
6 total要從找到的檔案中只挑出含某字串的檔案,就在 xargs 後面加上 grep -l。含 wp-login 的檔案有存取記錄和錯誤記錄兩個。
find /root/work/logs -name '*.log' -print0 | xargs -0 grep -l wp-login/root/work/logs/access.log
/root/work/logs/error.log4️⃣ xargs 指令刪除檔案
在 xargs 後面加上 rm,找到的檔案會一次刪除,所以刪除前要先確認會傳遞哪些檔案。在 rm 前面放 echo,就只會輸出要執行的指令行,檔案維持不動。
find /root/work/tmp -name '*.tmp' -print0 | xargs -0 echo rmrm /root/work/tmp/cache-a.tmp /root/work/tmp/cache-b.tmp /root/work/tmp/cache-c.tmpls tmpcache-a.tmp cache-b.tmp cache-c.tmp keep.txt加上 -p 後,每個指令都會詢問是否執行。輸入 n 就什麼都不刪,三個暫存檔維持不動。
find /root/work/tmp -name '*.tmp' -print0 | xargs -0 -p rmrm /root/work/tmp/cache-a.tmp /root/work/tmp/cache-b.tmp /root/work/tmp/cache-c.tmp?...nls tmpcache-a.tmp cache-b.tmp cache-c.tmp keep.txt輸入 y,三個檔案會被刪除,只留下 keep.txt。
find /root/work/tmp -name '*.tmp' -print0 | xargs -0 -p rmrm /root/work/tmp/cache-a.tmp /root/work/tmp/cache-b.tmp /root/work/tmp/cache-c.tmp?...yls tmpkeep.txt輸入為空時,xargs 會以無引數執行指令一次。傳入空檔案時 rm 會無引數執行,出現 [rm: missing operand] 錯誤;加上 -r 則完全不執行指令。
cat empty.txt | xargs rmrm: missing operand
Try 'rm --help' for more information.cat empty.txt | xargs -r rm5️⃣ xargs 平行執行、分隔符號與選項
🔲 平行執行與分隔符號
指令逐一依序執行時,對象一多時間也跟著拉長。-P 決定同時執行的指令數。等待 1、2、3、4 秒的四個 sleep,依序執行要 10 秒,以 -P 4 同時執行則在最長的 4 秒內結束。
time seq 1 4 | xargs -n 1 sleep
real 0m10.007s
user 0m0.004s
sys 0m0.003stime seq 1 4 | xargs -n 1 -P 4 sleep
real 0m4.005s
user 0m0.001s
sys 0m0.006s輸入以換行或空格以外的符號分隔時,就用 -d 指定分隔符號。用 -d , 切開以逗號連接的三個名稱,每個名稱輸出一行。
printf 'alice,bob,carol' | xargs -d , -n 1 echoalice
bob
carol要從檔案而非標準輸入讀取,就在 -a 寫上檔案名稱。不用管線,names.txt 的五個名稱就交給了 echo。
xargs -a names.txt echoalice bob carol dave erin🔲 xargs 指令選項
📌 主要選項:本文實際執行的結果
| 選項 | 作用 | 本文看到的結果 | |
|---|---|---|---|
| -n | 決定每次指令傳遞的引數數量 | 五個名稱以 -n 2 每兩個一組,echo 執行三次 | |
| -I | 每次把一行放進佔位字元,逐行執行 | 名稱放進 {} 的位置,與 -n 同時寫時 -I 會連同警告被忽略 | |
| -L | 決定每次指令傳遞的行數 | 在每行只有一個名稱的檔案中,結果與 -n 2 相同 | |
| -t | 先輸出要執行的指令行 | 指令行先於輸出出現 | |
| -0 | 只以空字元切分輸入(搭配 find -print0) | 不加時含空格的名稱被拆開,出現兩行錯誤;加上時三個檔案都是 6 行 | |
| -p | 每個指令都詢問是否執行 | n 時維持不動,y 時刪除三個檔案 | |
| -r | 輸入為空時不執行指令 | 不加時 [rm: missing operand],加上時不執行 | |
| -P | 決定同時執行的指令數 | 四個 sleep 依序 10 秒,-P 4 為 4 秒 | |
| -d | 決定切分輸入的分隔符號 | -d , 每個名稱一行 | |
| -a | 從檔案而非標準輸入讀取輸入 | names.txt 的五個名稱交給一次 echo |
📎 其他選項:依官方手冊
| 選項 | 作用 | |
|---|---|---|
| -s | 決定一行指令的最大字元數 | |
| -x | 超過 -s 大小時不執行就結束 | |
| -E | 在輸入中遇到只含此文字的行,就不再讀取其餘輸入 | |
| -o | 把執行指令的標準輸入重新開到終端機(用於互動式程式) | |
| --process-slot-var | 為同時執行的每個指令在環境變數放入不同編號 |
🔲 xargs 指令模擬器
在下面的模擬器中,可對相同的測試檔案親自輸入 xargs 與 find 指令。
🔢 FAQ & 推薦內容
ℹ️ 聯盟行銷說明
本站內容包含聯盟行銷連結。訪客透過這些連結購買商品或服務時,本站會從賣家獲得佣金。在這個過程中,購買者支付的金額(遇到活動折扣時金額會降低↓)並不會因此提高。刊登的價格、折扣與庫存資訊以撰寫當時為準,可能與實際情況不同,購買前請向賣家做最後確認。商品的挑選與評價依本站自訂的標準撰寫,是否支付佣金不會影響介紹順序或評價內容。