คำสั่ง xargs: วิธีใช้ ตัวเลือก -n และ -I และการใช้ร่วมกับ find
คำสั่ง xargs คือเครื่องมือ Linux ที่เปลี่ยนบรรทัดและคำจากอินพุตมาตรฐานให้เป็นอาร์กิวเมนต์ของคำสั่งอื่นแล้วรันคำสั่งนั้น เมื่อเราส่งไฟล์ล็อก 3 ไฟล์ที่ find พบไปให้ wc ผ่าน xargs ในโฟลเดอร์ทำงานบนเซิร์ฟเวอร์ AlmaLinux 9 ไฟล์ที่มีช่องว่างในชื่อถูกแยกเป็นสองส่วนจนเกิดข้อผิดพลาด และเมื่อใส่ -print0 กับ -0 จำนวนบรรทัดของทั้ง 3 ไฟล์ก็แสดงครบ
เอาต์พุตด้านล่างรันในโฟลเดอร์ทำงานด้วยบัญชี root บนเซิร์ฟเวอร์ AlmaLinux 9.8 รายชื่อ ล็อก และไฟล์ชั่วคราวเป็นไฟล์ตัวอย่างที่สร้างไว้ทดสอบ ส่วนที่อยู่ 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️⃣ ตัวเลือก -n และ -I ของ xargs
ถ้าไม่มีตัวเลือก อินพุตทั้งหมดจะเข้าไปในคำสั่งครั้งเดียว ถ้าต้องการรันซ้ำให้กำหนดจำนวนอาร์กิวเมนต์ต่อครั้งด้วย -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 total-print0 ของ find คั่นชื่อด้วยอักขระ null แทนการขึ้นบรรทัดใหม่ และ -0 ของ xargs แบ่งอาร์กิวเมนต์ด้วยอักขระ null นั้นเท่านั้น เมื่อใช้ทั้งสองจะได้จำนวนบรรทัดครบสามไฟล์ รวมไฟล์ที่มีช่องว่างด้วย
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ตัวเลือก -exec ของ find ทำงานเดียวกันได้ ถ้าใส่ + หลัง {} จะส่งไฟล์ที่พบไปครั้งเดียว ผลจึงเหมือนกัน และ find ส่งช่องว่างในชื่อไฟล์ไปตามเดิม xargs รับเอาต์พุตของคำสั่งอื่นได้ด้วย จึงใช้เมื่ออินพุตไม่ได้มาจาก find อย่างเดียว หรือเมื่อต้องกำหนดจำนวนต่อครั้ง (-n) หรือจำนวนการรันพร้อมกัน (-P)
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ถ้าต้องการเลือกเฉพาะไฟล์ที่มีสตริงจากไฟล์ที่พบ ให้ใส่ grep -l หลัง xargs ไฟล์ที่มี 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
ถ้าใส่ rm หลัง xargs ไฟล์ที่พบจะถูกลบทีเดียว จึงควรตรวจก่อนลบว่าไฟล์ใดจะถูกส่งไป ถ้าใส่ echo หน้า rm จะแสดงเฉพาะบรรทัดคำสั่งที่จะรัน และไฟล์ยังอยู่เหมือนเดิม
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 กำหนดจำนวนคำสั่งที่รันพร้อมกัน sleep สี่ตัวที่รอ 1, 2, 3 และ 4 วินาที ใช้เวลา 10 วินาทีเมื่อรันตามลำดับ และจบใน 4 วินาทีซึ่งนานที่สุดเมื่อรันพร้อมกันด้วย -P 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 | แบ่งอินพุตด้วยอักขระ null เท่านั้น (ใช้กับ 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 & เนื้อหาแนะนำ
การค้นหาสตริง
คำสั่ง grep ของ Linux
คำสั่ง grep ใช้หาบรรทัดในไฟล์ที่ตรงกับสตริงและนิพจน์ปกติ ใช้เมื่อต้องการค้นหาหลายไฟล์ที่ส่งผ่าน xargs ในครั้งเดียว
การลบไฟล์
คำสั่ง rm ของ Linux
บทความเรื่องคำสั่ง rm ที่ลบไฟล์และโฟลเดอร์ รวมถึงอันตรายของตัวเลือก -rf ตรวจตัวเลือกก่อนใส่ rm หลัง xargs
การปิดโปรเซส
คำสั่ง kill ของ Linux
คำสั่ง kill ส่งสัญญาณไปยังหมายเลขโปรเซสเพื่อปิดโปรเซส ใช้ต่อเมื่อส่งรายการหมายเลขโปรเซสผ่าน xargs เพื่อปิด
ℹ️ ประกาศเรื่องลิงก์แอฟฟิลิเอต
เนื้อหาของเว็บไซต์นี้มีลิงก์แอฟฟิลิเอต หากผู้เข้าชมซื้อสินค้าหรือบริการผ่านลิงก์เหล่านี้ เว็บไซต์นี้จะได้รับค่าคอมมิชชันจากผู้ขาย ในกระบวนการนี้ ราคาที่ผู้ซื้อจ่าย(ราคาจะลดลงเมื่อมีโปรโมชัน↓)จะไม่สูงขึ้นแต่อย่างใด ราคา ส่วนลด และข้อมูลสต็อกที่แสดงเป็นข้อมูล ณ เวลาที่เขียนและอาจต่างจากความเป็นจริง โปรดตรวจสอบกับผู้ขายอีกครั้งก่อนซื้อ การเลือกและการประเมินสินค้าเขียนตามเกณฑ์ของเราเอง และการได้รับค่าคอมมิชชันหรือไม่ไม่มีผลต่อลำดับการแนะนำหรือเนื้อหาการประเมิน