xargs 指令:用法、-n 與 -I 選項,以及搭配 find 使用

測試環境RHEL 系列AlmaLinux 9.8root 帳號2026-10-29 確認

xargs 指令是把從標準輸入收到的行與字詞轉成另一個指令的引數並執行的 Linux 工具。我們在 AlmaLinux 9 伺服器的工作資料夾中,把 find 找到的三個記錄檔透過 xargs 交給 wc,結果檔名含空格的一個檔案被拆成兩個而發生錯誤;加上 -print0 與 -0 後,三個檔案的行數都顯示出來了。

以下輸出是在 AlmaLinux 9.8 伺服器上以 root 帳號於工作資料夾內執行的結果。名稱清單、記錄檔和暫存檔是為測試建立的範例檔案,其中的 IP 位址和工作資料夾路徑也是範例值。

1️⃣ xargs 指令基本用法

  • ↪️ 把標準輸入變成指令的引數

xargs 把前一個指令傳來的標準輸入依空格和換行切開,放到後面所寫指令的引數位置再執行。我們用每行一個名稱的 names.txt 確認。

cat names.txt
alice
bob
carol
dave
erin

把 cat 的輸出交給 xargs echo,五行會成為 echo 一次的引數,顯示成一行。

cat names.txt | xargs echo
alice bob carol dave erin

後面不寫指令時,xargs 會執行 echo,所以結果相同。

cat names.txt | xargs
alice bob carol dave erin

管線是把前一個指令的輸出接到後一個指令標準輸入的通道,因此後一個指令的引數位置什麼也沒有。把含有三個檔名的 list.txt 只用管線交給 wc -l,wc 會計算清單本身的 3 行。

cat list.txt
logs/access.log
logs/error.log
tmp/keep.txt
cat list.txt | wc -l
3

中間放入 xargs,清單裡的三個名稱就成為 wc 的引數,顯示每個檔案的行數。

cat list.txt | xargs wc -l
  3 logs/access.log
  2 logs/error.log
  1 tmp/keep.txt
  6 total

2️⃣ xargs -n 與 -I 選項

  • ↪️ 分組大小、引數位置與 -t 確認

沒有選項時,所有輸入都進入一次指令,因此要重複執行指令,就用 -n 決定每次傳遞的引數數量。下圖可確認相同的五個名稱如何依選項分組。

🧩 xargs 把標準輸入分組成指令引數的方式
說明圖解
⚙️ 選項
$ cat names.txt | xargs echo
$ cat names.txt | xargs -n 2 echo
$ cat names.txt | xargs -I {} echo 'user: {}'
① 標準輸入 (names.txt)alicebobcaroldaveerin每行一個名稱,共五行。
② 分組成引數alicebobcaroldaveerin沒有選項時,五個成為一組。alicebobcaroldaveerin-n 2 每兩個一組,剩下的一個自成一組。alicebobcaroldaveerin-I {} 把一行當成一組,放進 {} 的位置。
③ 執行的指令與輸出echo alice bob carol dave erinalice bob carol dave erinecho 執行一次。echo alice bobecho carol daveecho erinecho 執行三次,每組輸出一行。echo 'user: alice' echo 'user: bob' … 以相同形式到 erin 共五次user: aliceuser: bobuser: caroluser: daveuser: erinecho 執行五次,名稱放進 {} 的位置。
沒有選項時,xargs 把從輸入讀到的所有字詞都當成一次指令的引數。五個名稱交給一次 echo,顯示成一行。
加上 -n 2,字詞每兩個一組,重複執行指令。五個名稱成為三組,所以 echo 執行三次。
加上 -I {},一行視為一個單位,把該行放進指令中 {} 的位置,每行執行一次。引數必須放在最後以外的位置時使用。

-n 1 對每個名稱執行 echo,輸出五行。

cat names.txt | xargs -n 1 echo
alice
bob
carol
dave
erin

-n 2 每兩個一組,剩下的一個另外傳遞。

cat names.txt | xargs -n 2 echo
alice bob
carol dave
erin

要親眼確認執行的指令,就加上 -t。指令行會先出現,下面接著輸出。

cat names.txt | xargs -t -n 2 echo
echo 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: erin
cat names.txt | xargs -I {} echo '{} -> home/{}'
alice -> home/alice
bob -> home/bob
carol -> home/carol
dave -> home/dave
erin -> home/erin

同樣的方式可依名稱建立資料夾。先建立 home 資料夾,再用 -I {} 在其下建立各名稱的資料夾,就會產生五個資料夾。

mkdir home
cat names.txt | xargs -I {} mkdir home/{}
ls home
alice  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 echo
alice bob
carol dave
erin

3️⃣ find 與 xargs 組合

  • ↪️ 用 -print0 與 -0 傳遞含空格的檔名

不必手動建立名稱清單,也能把 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 total

find 的 -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 total

find 的 -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.log

4️⃣ xargs 指令刪除檔案

  • ↪️ 先用 echo 查看,再用 -p 確認

在 xargs 後面加上 rm,找到的檔案會一次刪除,所以刪除前要先確認會傳遞哪些檔案。在 rm 前面放 echo,就只會輸出要執行的指令行,檔案維持不動。

find /root/work/tmp -name '*.tmp' -print0 | xargs -0 echo rm
rm /root/work/tmp/cache-a.tmp /root/work/tmp/cache-b.tmp /root/work/tmp/cache-c.tmp
ls tmp
cache-a.tmp  cache-b.tmp  cache-c.tmp  keep.txt

加上 -p 後,每個指令都會詢問是否執行。輸入 n 就什麼都不刪,三個暫存檔維持不動。

find /root/work/tmp -name '*.tmp' -print0 | xargs -0 -p rm
rm /root/work/tmp/cache-a.tmp /root/work/tmp/cache-b.tmp /root/work/tmp/cache-c.tmp?...n
ls tmp
cache-a.tmp  cache-b.tmp  cache-c.tmp  keep.txt

輸入 y,三個檔案會被刪除,只留下 keep.txt。

find /root/work/tmp -name '*.tmp' -print0 | xargs -0 -p rm
rm /root/work/tmp/cache-a.tmp /root/work/tmp/cache-b.tmp /root/work/tmp/cache-c.tmp?...y
ls tmp
keep.txt

輸入為空時,xargs 會以無引數執行指令一次。傳入空檔案時 rm 會無引數執行,出現 [rm: missing operand] 錯誤;加上 -r 則完全不執行指令。

cat empty.txt | xargs rm
rm: missing operand
Try 'rm --help' for more information.
cat empty.txt | xargs -r rm

5️⃣ xargs 平行執行、分隔符號與選項

  • ↪️ -P、-d、-a 選項

🔲 平行執行與分隔符號

指令逐一依序執行時,對象一多時間也跟著拉長。-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.003s
time 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 echo
alice
bob
carol

要從檔案而非標準輸入讀取,就在 -a 寫上檔案名稱。不用管線,names.txt 的五個名稱就交給了 echo。

xargs -a names.txt echo
alice 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 指令。

xargs 指令模擬器GNU findutils 4.8
[root@server work]#
用鍵盤 ↑↓ 鍵可叫出先前輸入過的指令。

🔢 FAQ & 推薦內容

傳遞處理程序編號後,kill 會向該編號傳送訊號。用 Shell 變數 $! 取出背景執行的 sleep 600 的處理程序編號並交給 xargs kill,工作清單留下 [Terminated sleep 600],下一次 jobs 時工作已消失。用其他指令收集編號清單時,要先輸出確認包含哪些處理程序再傳遞。

--show-limits 選項會輸出限制。在測試的伺服器上,指令行長度的 POSIX 上限是 2,093,890 位元組,xargs 實際使用的指令緩衝區是 131,072 位元組。依手冊說明,輸入比這個緩衝區長時,xargs 會把指令分成多次執行。

xargs 執行的指令中只要有一個以 1 到 125 之間的代碼失敗,xargs 的結束代碼就是 123。含空格檔名被拆開的 wc 執行和以空輸入執行 rm 的情況都是 123,找不到指令的情況則是 127。在 Shell 指令碼中檢查 xargs 之後的結束代碼時,以這個值為基準。

ℹ️ 聯盟行銷說明
本站內容包含聯盟行銷連結。訪客透過這些連結購買商品或服務時,本站會從賣家獲得佣金。在這個過程中,購買者支付的金額(遇到活動折扣時金額會降低↓)並不會因此提高。刊登的價格、折扣與庫存資訊以撰寫當時為準,可能與實際情況不同,購買前請向賣家做最後確認。商品的挑選與評價依本站自訂的標準撰寫,是否支付佣金不會影響介紹順序或評價內容。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

Prove your humanity: 1   +   4   =