พอร์ทัลข้อมูลความปลอดภัย Xargs: กรณีการใช้งานหลายกรณี

ในตอนเย็นที่ยาวนานของฤดูหนาว ฉันนั่งและคิดว่า "เมื่อถึงเวลากลางวัน ฉันจะนั่งลงและจัดการกับยูทิลิตี้ xarg อันลึกลับนี้อย่างเหมาะสม" ดูเหมือนว่าจะถึงเวลาแล้ว - ฉันนั่งลงเพื่อคิดออก สิ่งแรกที่ดึงดูดสายตาของฉันก็คือผู้ชายคนนี้ค่อนข้างลึกลับและไม่ได้เคลียร์อะไรในครั้งแรก ในวิกิพีเดียก็ไม่ได้เพิ่มข้อมูลเชิงลึกใดๆ เลย แต่ฉันสับสนด้วยซ้ำ ดังนั้นฉันจึงตัดสินใจดำเนินการสอบสวนของตัวเองและเขียนเกี่ยวกับเรื่องนี้ คู่มือขนาดเล็กเด็กน้อย เท่าที่ทราบตราบใดที่คุณอธิบายคุณจะเข้าใจ :)

ดังนั้น xargs

xargs เป็นโปรแกรมอรรถประโยชน์บรรทัดคำสั่งที่ช่วยให้คุณสามารถเรียกใช้คำสั่งใด ๆ ที่มีอาร์กิวเมนต์ที่นำมาได้ อินพุตมาตรฐาน- นอกจากนี้ อาร์กิวเมนต์สามารถส่งผ่านทั้งหมดในคราวเดียวหรืออาจจัดกลุ่มออกเป็นหลายส่วนก็ได้ เราจะศึกษา xargs เวอร์ชัน 4.4.0 และตามคำแนะนำของชายคนนี้ เราจะใช้เฉพาะอาร์กิวเมนต์ใหม่ที่ไม่ได้ทำเครื่องหมายว่าเลิกใช้แล้ว (จะดีกว่าหากคุ้นเคยกับการทำงานอย่างถูกต้องทันที)

ดังนั้นสิ่งแรกที่ต้องทำความเข้าใจคือวิธีที่ xargs ประมวลผลสตรีมขาเข้าและแบ่งออกเป็นอาร์กิวเมนต์ มีหลายโหมด ขึ้นอยู่กับตัวเลือก:

1. ปกติ. ตามค่าเริ่มต้น ตัวแยกอาร์กิวเมนต์คืออักขระช่องว่าง: ช่องว่าง แท็บ แท็บแนวตั้ง หรือการขึ้นบรรทัดใหม่ แต่เหมือนใน เชลล์คำสั่งคุณสามารถใช้ "" หรือ \ เพื่อป้องกันการแยกอาร์กิวเมนต์

2. ปกติ มีการจัดกลุ่ม โหมดเปิดใช้งานโดยพารามิเตอร์ -L เกือบจะเหมือนกันกับอันก่อนหน้า ยกเว้นว่า xargs จะจดจำอาร์กิวเมนต์ใดอยู่บนบรรทัดใด นอกจากนี้ หากบรรทัดลงท้ายด้วยช่องว่างหรือแท็บ บรรทัดถัดไปถือเป็นการต่อยอดจากปัจจุบัน

3.ทีละบรรทัด เปิดใช้งานเมื่อใช้ตัวเลือก -I หรือ -0 ในกรณีนี้ สตริงทั้งหมดจะถือเป็นอาร์กิวเมนต์ทั้งหมด 1 รายการ แม้ว่าจะมีช่องว่างและแท็บอยู่ข้างในก็ตาม สำหรับ -I ท้ายบรรทัดคืออักขระ "\n" และสำหรับ -0 อักขระ "\0"

เรามาทำแบบทดสอบสองสามข้อเพื่อทำความเข้าใจทั้งหมดนี้กันดีกว่า มาสร้างการทดสอบไฟล์ด้วยเนื้อหาดังต่อไปนี้ (== ไม่จำเป็นต้องป้อนลงในไฟล์):
==
หาเรื่อง1
พื้นที่ arg2
"ยกมา arg3"
arg4\ หลบหนี
arg5 ด้วย
ดำเนินการต่อ
==
(ต้องมีช่องว่างหลัง "arg5 with")
นอกจากนี้ เรายังเขียนสคริปต์ tp เล็กๆ ที่จะส่งออกอาร์กิวเมนต์ โดยคั่นด้วยสัญลักษณ์ “:” และปริมาณ:
==
#!/bin/bash
เสียงสะท้อน -n "@$#"
ในขณะที่ [[ $1 != "" ]]; ทำ echo -n ":$1"; กะ; เสร็จแล้ว
เสียงสะท้อน
==

โหมดปกติ (ข้อโต้แย้งคั่นด้วยช่องว่าง):
x $ การทดสอบแมว | xargs ./tp
@8:arg1:arg2:space:arg3 อ้างถึง:arg4 หนี:arg5:with:continue
ไฟล์ถูกแบ่งออกเป็นอาร์กิวเมนต์โดยใช้อักขระช่องว่าง แต่บรรทัดที่ยกมาและยกเว้นด้วยอักขระ "\" ยังคงไม่เสียหาย

โหมดปกติที่มีการจัดกลุ่มตามแถวไม่แตกต่างจากโหมดก่อนหน้าในขั้นตอนนี้

การแยกบรรทัด. มาสร้างไฟล์ทดสอบที่สองด้วยคำสั่งต่อไปนี้:
x $ cp ทดสอบ testz && printf "\0arg6" >> testz
มาตรวจสอบกัน
x $ cat testz | xargs -0 ./tp
@2:arg1
พื้นที่ arg2
"ยกมา arg3"
arg4\ หลบหนี
arg5 ด้วย
ดำเนินการต่อ
:arg6

อย่างที่คุณเห็น มีเพียง 2 อาร์กิวเมนต์เท่านั้น ข้อโต้แย้งแรกคือแบบยาว โดยคงการขึ้นบรรทัดใหม่ เครื่องหมายคำพูด และ \ และข้อโต้แย้งที่สองคือ arg6 ในไฟล์จะถูกคั่นด้วยอักขระ null

เกี่ยวกับการแยกพารามิเตอร์ สามารถพูดได้อีกเรื่องหนึ่งเกี่ยวกับตัวเลือก -d ซึ่งระบุตัวคั่นใหม่ ตัวอย่างเช่น ลองใช้ "3" เป็นตัวคั่น
x $ การทดสอบแมว | xargs -d 3 ./tp
@2:arg1
พื้นที่ arg2
"หาเรื่อง: ยกมา"
arg4\ หลบหนี
arg5 ด้วย
ดำเนินการต่อ
ไฟล์ถูกแบ่งออกเป็น 2 ส่วนตรงตำแหน่งของสัญลักษณ์ "3" สิ่งที่น่าทึ่งคือวิธีนี้คุณสามารถจำลองตัวเลือก -0 ได้
x $ cat testz | xargs -d "\x00" ./tp
@2:arg1
พื้นที่ arg2
"ยกมา arg3"
arg4\ หลบหนี
arg5 ด้วย
ดำเนินการต่อ
:arg6

ดูเหมือนว่าเราได้แยกการแบ่งอินพุตสตรีมออกเป็นอาร์กิวเมนต์แล้ว มาดูการทดแทนพารามิเตอร์กันดีกว่า

ดังนั้น หลังจากตัวเลือกแล้ว xarg จะรอคำสั่งซึ่งคำสั่งจะดำเนินการ อาร์กิวเมนต์ที่เข้ามาทั้งหมดจะถูกแบ่งออกเป็นกลุ่มหลังจากนั้น ได้รับคำสั่งถูกเรียกสำหรับแต่ละกลุ่ม และอาร์กิวเมนต์ทั้งหมดจากกลุ่มนั้นจะถูกส่งผ่านไปยังกลุ่มนั้น

ตอนนี้เรามาดูกันว่ากลุ่มต่างๆ เกิดขึ้นได้อย่างไร

1. หากไม่มีตัวเลือก แสดงว่ามีเพียงกลุ่มเดียว อาร์กิวเมนต์ทั้งหมดจากสตรีมอินพุตจะตกอยู่ในกลุ่มนั้น พูดง่ายๆ ก็คือกลุ่มที่มีขนาดไม่สิ้นสุด :)

2. ตัวเลือก -L n ระบุการจัดกลุ่มตามบรรทัด คำสั่งถูกส่งผ่านอาร์กิวเมนต์ใน n บรรทัด ฉันจะสาธิตด้วยตัวอย่าง
จัดกลุ่มตาม 1 บรรทัด:
x $ การทดสอบแมว | xargs -L 1 ./tp
@1:arg1
@2:arg2:ช่องว่าง
@1:arg3 ยกมา
@1:arg4 หลบหนี
@3:arg5:กับ:ดำเนินการต่อ
คุณจะเห็นว่าบรรทัดที่สองมี 2 อาร์กิวเมนต์ เนื่องจากทั้งคู่อยู่ในบรรทัดเดียวกัน และอันสุดท้ายคือ 3 จริงๆ เนื่องจากบรรทัดสุดท้ายนั้น “ยาวขึ้น” เนื่องจากมีช่องว่างที่ส่วนท้าย

ตอนนี้จัดกลุ่มเป็น 2 บรรทัด คำสั่งประกอบด้วยบรรทัดที่ 1 และ 2; 3 และ 4; และเด็กกำพร้าคนที่ 5:
x $ การทดสอบแมว | xargs -L 2 ./tp
@3:arg1:arg2:ช่องว่าง
@2:arg3 อ้างอิง:arg4 หลบหนี
@3:arg5:กับ:ดำเนินการต่อ

3. การจัดกลุ่มตามอาร์กิวเมนต์ ระบุโดยตัวเลือก -n x ที่นี่ทุกอย่างโปร่งใส: อาร์กิวเมนต์จะถูกจัดกลุ่มเป็น x ชิ้นและส่งผ่านไปยังคำสั่ง
สำหรับหนึ่งข้อโต้แย้ง:
x $ การทดสอบแมว | xargs -n 1 ./tp
@1:arg1
@1:arg2
@1:ช่องว่าง
@1:arg3 ยกมา
@1:arg4 หลบหนี
@1:arg5
@1:กับ
@1:ดำเนินการต่อ
แต่ละข้อโต้แย้ง 2 ข้อ:
x $ การทดสอบแมว | xargs -n 2 ./tp
@2:arg1:arg2
@2:space:arg3 ยกมา
@2:arg4 หลบหนี:arg5
@2:กับ:ดำเนินการต่อ

3. โหมดการทดแทน - ตัวเลือก -I อันดับแรกเราต้องระลึกไว้ว่าใน โหมดนี้อาร์กิวเมนต์จากสตรีมอินพุตจะถูกแยกวิเคราะห์ต่างกัน แต่ละบรรทัดคือหนึ่งอาร์กิวเมนต์ทั้งหมด บรรทัดจะไม่ต่อกัน ประการที่สองตัวเลือก -I มีพารามิเตอร์ - สตริงซึ่งถูกแทนที่ด้วยคำสั่งด้วยอาร์กิวเมนต์:
x $ echo -e "A B\nC D" | xargs -I _ ./tp =_+_=
@1:=เอบี+เอบี=
@1:=ซี ดี+ซี ดี=
สังเกตได้ง่ายว่าอักขระ _ ถูกระบุเป็นสตริงการแทนที่อาร์กิวเมนต์ ซึ่งใช้ 2 ครั้งในคำสั่ง คุณจะเห็นได้ว่าอาร์กิวเมนต์ได้รับการจัดสรรเป็นทั้งบรรทัด และพื้นที่ว่างไม่ส่งผลต่อการแยกวิเคราะห์ คำสั่งถูกเรียกสำหรับแต่ละอาร์กิวเมนต์

นั่นคือทั้งหมดที่มีการทดแทน ลองดูตัวเลือกที่สำคัญที่เหลือ
-r - อย่ารันคำสั่งหากไม่มีข้อโต้แย้ง:
x $ cat /dev/null | xargs ./tp
@0
x $ cat /dev/null | xargs -r ./tp
x$
อย่างที่คุณเห็นในกรณีที่สองคำสั่งไม่ได้ถูกดำเนินการ

P - xargs จะขอการยืนยันเพื่อดำเนินการแต่ละคำสั่ง

เป็นการสิ้นสุดบทช่วยสอนสั้นๆ ปรากฏว่าไม่สั้นมากแต่หวังว่าจะเข้าใจนะครับ ;)

หลีกเลี่ยงแนวทางปฏิบัติ UNIX ที่ไม่ดี

มักใช้ระบบใดๆ ก็ตาม เราก็จะคุ้นเคยกับรูปแบบการทำงานบางอย่าง แต่เทมเพลตเหล่านี้ไม่ได้เหมาะสมที่สุดเสมอไป บางครั้งเรายังพัฒนานิสัยที่ไม่ดีซึ่งนำไปสู่ความยุ่งเหยิงและความซุ่มซ่ามในที่ทำงาน หนึ่งใน วิธีที่ดีที่สุดการแก้ไขข้อบกพร่องดังกล่าวคือการสร้างนิสัยในการใช้เทคนิคที่ดีเพื่อป้องกันความยุ่งเหยิง บทความนี้นำเสนอ 10 วิธีในการทำงานเป็นทีม สตริงยูนิกซ์นิสัยที่มีค่าซึ่งจะช่วยให้คุณหลีกเลี่ยงข้อบกพร่องทั่วไปและปรับปรุงประสิทธิภาพการทำงานของคุณ คำอธิบายโดยละเอียดแต่ละวิธีจะได้รับหลังรายการ

มาเรียนรู้นิสัยที่ดี 10 ประการกัน

สิบวิธีที่ดีในการทำความคุ้นเคย:

สร้างแผนผังไดเร็กทอรีด้วยคำสั่งเดียว

รายการ 1 แสดงให้เห็นถึงความล้มเหลวของ UNIX ที่พบบ่อยที่สุด: การระบุแผนผังไดเร็กทอรีทีละขั้นตอน

รายการ 1. ตัวอย่าง วิธีการที่ไม่ดีงาน #1: คำจำกัดความทีละขั้นตอนของแผนผังไดเร็กทอรี
~ $ mkdir tmp ~ $ cd tmp ~/tmp $ mkdir a ~/tmp $ cd a ~/tmp/a $ mkdir b ~/tmp/a $ cd b ~/tmp/a/b/ $ mkdir c ~/tmp /a/b/ $ ซีดี c ~/tmp/a/b/c $

การใช้ตัวเลือก -p mkdir เร็วกว่ามากและสร้างไดเร็กทอรีพาเรนต์และไดเร็กทอรีย่อยทั้งหมดด้วยคำสั่งเดียว แต่แม้แต่ผู้ดูแลระบบที่รู้เกี่ยวกับตัวเลือกนี้ก็ยังทำงานทีละขั้นตอน โดยสร้างแต่ละไดเร็กทอรีย่อยแยกกันบนบรรทัดคำสั่ง ประหยัดเวลาของคุณ - ทำความคุ้นเคยกับมัน วิธีการที่ดี:

รายการ 2 ตัวอย่างวิธีการทำงานที่ดี #1: การกำหนดแผนผังไดเร็กทอรีด้วยคำสั่งเดียว
~ $ mkdir -p tmp/a/b/c

คุณสามารถใช้ตัวเลือกนี้เพื่อสร้างไม่เพียงแต่ลำดับชั้นธรรมดา แต่ยังรวมถึงแผนผังไดเร็กทอรีที่ซับซ้อนซึ่งสะดวกมากในการใช้งานในสคริปต์ ตัวอย่างเช่น:

รายการ 3 อีกตัวอย่างหนึ่งของวิธีการทำงานที่ดี #1: การกำหนดแผนผังไดเร็กทอรีที่ซับซ้อนด้วยคำสั่งเดียว
~ $ mkdir -p project/(lib/ext,bin,src,doc/(html,info,pdf),demo/stat/a)

ก่อนหน้านี้ มีเหตุผลเดียวเท่านั้นที่ต้องก้าวผ่านแผนผังไดเร็กทอรี - การใช้งาน mkdir ไม่รองรับตัวเลือกนี้ แต่สิ่งนี้ไม่เกี่ยวข้องกับระบบส่วนใหญ่อีกต่อไป ขณะนี้ IBM, AIX, mkdir, GNU mkdir และระบบอื่นๆ ที่เป็นไปตามข้อกำหนดคุณลักษณะ UNIX มีอ็อพชันนี้

สำหรับบางระบบที่ไม่มีคุณลักษณะนี้ คุณควรใช้สคริปต์ mkdirhier (ดู ) ซึ่งจะล้อม mkdir และดำเนินการฟังก์ชันเดียวกัน

~ $ โครงการ mkdirhier/(lib/ext,bin,src,doc/(html,info,pdf),demo/stat/a)

เปลี่ยนเส้นทาง อย่าถ่ายโอนไฟล์เก็บถาวร

วิธีการทำงานที่ไม่ดีอีกวิธีหนึ่งคือการย้ายไฟล์เก็บถาวร .tar ไปยังไดเร็กทอรีเฉพาะ หากคุณต้องการแตกไฟล์เก็บถาวรลงในไดเร็กทอรีนั้น คุณไม่ควรทำอย่างนั้น คุณสามารถแกะกล่องใดก็ได้ ไฟล์เก็บถาวร.tar ไปยังไดเร็กทอรีใด ๆ - นี่คือสิ่งที่ใช้ตัวเลือก -C ใช้ตัวเลือก -C เพื่อระบุไดเร็กทอรีที่จะคลายแพ็ก:

รายการ 4: ตัวอย่างวิธีแก้ปัญหาที่ดี #2: การใช้ตัวเลือก -C เพื่อแตกไฟล์เก็บถาวร .tar
~ $ tar xvf -C tmp/a/b/c newarc.tar.gz

การใช้ตัวเลือก -C จะดีกว่าในการย้ายไฟล์เก็บถาวรไปยังไดเร็กทอรีที่คุณต้องการ เปลี่ยนไดเร็กทอรี และแตกเนื้อหาของไฟล์ โดยเฉพาะอย่างยิ่งหากไฟล์เก็บถาวรนั้นอยู่ที่อื่น

รวมคำสั่งของคุณเข้ากับคำสั่งควบคุม

คุณคงทราบอยู่แล้วว่าในเชลล์ส่วนใหญ่ คุณสามารถรวมคำสั่งบนบรรทัดคำสั่งเดียวกันได้โดยใช้เครื่องหมายอัฒภาค (;) ระหว่างคำสั่งเหล่านั้น อัฒภาคเป็นตัวดำเนินการควบคุมเชลล์ และถึงแม้จะมีจุดมุ่งหมายเพื่อเชื่อมโยงคำสั่งหลายคำสั่งที่แยกจากกันเข้ากับบรรทัดคำสั่งเดียว แต่ก็ไม่สามารถใช้งานได้เสมอไป ตัวอย่างเช่น สมมติว่าคุณใช้อัฒภาคเพื่อเชื่อมสองคำสั่งเข้าด้วยกัน โดยที่การดำเนินการของคำสั่งที่สองนั้นขึ้นอยู่กับความสำเร็จของคำสั่งแรกทั้งหมด หากคำสั่งแรกไม่ทำงานตามที่คุณคาดหวัง คำสั่งที่สองจะยังคงทำงาน - และล้มเหลว ให้ใช้คำสั่งควบคุมที่เหมาะสมกว่าแทน (บางส่วนจะอธิบายไว้ในบทความนี้) หากเปลือกของคุณรองรับพวกมันได้ พวกมันต้องใช้เวลาพอสมควรในการทำความคุ้นเคย

รันคำสั่งเฉพาะเมื่อคำสั่งอื่นส่งคืนค่า null

ใช้ตัวดำเนินการควบคุม && เพื่อรวมสองคำสั่งเข้าด้วยกัน โดยที่คำสั่งที่สองจะถูกดำเนินการก็ต่อเมื่อคำสั่งแรกส่งคืนเท่านั้น ค่าว่าง- กล่าวอีกนัยหนึ่ง หากคำสั่งแรกสำเร็จ คำสั่งที่สองก็จะรันด้วย หากคำสั่งแรกไม่ถูกดำเนินการ คำสั่งที่สองจะไม่ทำงานเลย ตัวอย่างเช่น:

รายการ 5 ตัวอย่างของแนวปฏิบัติที่ดี #3: รวมคำสั่งเข้ากับคำสั่งควบคุม
~ $ ซีดี tmp/a/b/c && tar xvf ~/archive.tar

ตัวอย่างนี้จะแยกเนื้อหาของไฟล์เก็บถาวรลงในไดเร็กทอรี ~/tmp/a/b/c หากมีไดเร็กทอรีนั้นอยู่ หากไม่มีไดเร็กทอรี คำสั่ง tar จะไม่รัน และจะไม่มีการแตกไฟล์ใดๆ จากไฟล์เก็บถาวร

รันคำสั่งต่อเมื่อคำสั่งอื่นส่งคืนค่าที่ไม่ใช่ศูนย์เท่านั้น

ในทำนองเดียวกัน ตัวดำเนินการควบคุม || แยกทั้งสองคำสั่งและรันคำสั่งที่สองเฉพาะในกรณีที่คำสั่งแรกส่งคืนค่าที่ไม่เป็นศูนย์ กล่าวอีกนัยหนึ่งหากคำสั่งแรกคือ ประสบความสำเร็จคำสั่งที่สองจะไม่ทำงาน หากคำสั่งแรกล้มเหลว แสดงว่าคำสั่งที่สองล้มเหลว จะเริ่ม- โอเปอเรเตอร์นี้มักใช้เพื่อทดสอบว่ามีไดเร็กทอรีที่กำหนดอยู่หรือไม่ และหากไม่มี ก็จะสร้างขึ้นมา:

รายการ 6 อีกตัวอย่างหนึ่งของแนวปฏิบัติที่ดี #3: รวมคำสั่งเข้ากับคำสั่งควบคุม
~ $ ซีดี tmp/a/b/c || mkdir -p tmp/a/b/c

คุณยังสามารถรวมคำสั่งควบคุมที่อธิบายไว้ในส่วนนี้ได้ แต่ละรายการอ้างถึงคำสั่งสุดท้ายที่รัน:

รายการ 7. ตัวอย่างรวมของแนวปฏิบัติที่ดี #3: การรวมคำสั่งเข้ากับคำสั่งควบคุม
~ $ ซีดี tmp/a/b/c || mkdir -p tmp/a/b/c &&

ระวังเมื่อใช้เครื่องหมายคำพูดเมื่อทำงานกับตัวแปร

ควรระมัดระวังกับการขยายเชลล์และชื่อตัวแปรเสมอ จริงๆแล้วนี่คือ เป็นความคิดที่ดี- ใส่การอ้างอิงตัวแปรด้วยเครื่องหมายคำพูดคู่เฉพาะในกรณีที่ไม่มีเหตุผลพิเศษที่จะไม่ทำเช่นนั้น ในทำนองเดียวกัน หากชื่อตัวแปรตามด้วยข้อความตัวอักษรและตัวเลข จะต้องใส่ชื่อตัวแปรไว้ด้วย วงเล็บปีกกา(()) เพื่อแยกความแตกต่างจากข้อความโดยรอบ มิฉะนั้น เชลล์จะตีความข้อความต่อท้ายเป็นส่วนหนึ่งของชื่อตัวแปร และผลลัพธ์ที่เป็นไปได้มากที่สุดก็คือ รหัสศูนย์กลับ. รายการที่ 8 แสดงตัวอย่างการใช้เครื่องหมายคำพูดกับชื่อตัวแปรและผลลัพธ์

รายการ 8 ตัวอย่างของแนวปฏิบัติที่ดี #4: การใช้ (และไม่ใช้) เครื่องหมายคำพูดเมื่อทำงานกับตัวแปร
~ $ ls tmp/ ab ~ $ VAR="tmp/*" ~ $ echo $VAR tmp/a tmp/b ~ $ echo "$VAR" tmp/* ~ $ echo $VARa ~ $ echo "$VARa" ~ $ เสียงสะท้อน "$(VAR)a" tmp/*a ~ $ เสียงสะท้อน $(VAR)a tmp/a ~ $

ใช้ลำดับหลีกเพื่อป้อนสตริงแบบยาว

คุณอาจเคยเห็นตัวอย่างของโค้ดที่แบ็กสแลช (\) ยังคงเป็นบรรทัดยาว และคุณรู้ว่าเชลล์ส่วนใหญ่จะถือว่าสิ่งที่คุณพิมพ์ในบรรทัดต่อมาที่รวมแบ็กสแลชเป็นบรรทัดยาวหนึ่งบรรทัด อย่างไรก็ตาม คุณจะได้รับประโยชน์มากขึ้นจากฟีเจอร์บรรทัดคำสั่งนี้โดยใช้งานบ่อยขึ้น แบ็กสแลชมีประโยชน์อย่างยิ่งหากเทอร์มินัลของคุณไม่สามารถจัดการการแบ่งหลายบรรทัดได้อย่างถูกต้อง หรือเมื่อบรรทัดคำสั่งสั้นกว่าปกติ (ตัวอย่างเช่น เมื่อคุณมี ทางยาว- แบ็กสแลชยังมีประโยชน์ในการเน้นส่วนต่างๆ ของความหมายอีกด้วย เส้นยาวดังตัวอย่างต่อไปนี้:

รายการ 9 ตัวอย่างของแนวปฏิบัติที่ดี #5: การใช้แบ็กสแลชกับสตริงที่ยาว
~ $ ซีดี tmp/a/b/c || \ > mkdir -p tmp/a/b/c && \ > tar xvf -C tmp/a/b/c ~/archive.tar

อีกทางเลือกหนึ่ง นี่คือการกำหนดค่าอื่นที่ใช้งานได้:

รายการ 10 อีกตัวอย่างหนึ่งของแนวปฏิบัติที่ดี #5: การใช้เครื่องหมายแบ็กสแลชกับสตริงที่ยาว
~ $ ซีดี tmp/a/b/c \ > || \ > mkdir -p tmp/a/b/c \ > && \ > tar xvf -C tmp/a/b/c ~/archive.tar

เมื่อคุณแบ่งสตริงออกเป็นหลายบรรทัด เชลล์จะถือว่าสตริงนั้นเป็นทั้งสตริงเดียวเสมอ โดยจะลบเครื่องหมายแบ็กสแลชและช่องว่างเพิ่มเติมทั้งหมดออกจากสตริงยาวที่เป็นผลลัพธ์

บันทึก:ในเชลล์ส่วนใหญ่ เมื่อคุณกดลูกศรขึ้น เส้นหลายบรรทัดทั้งหมดจะแสดงเป็นเส้นยาวเส้นเดียว

รวมคำสั่งเข้าเป็นรายการ

เชลล์ส่วนใหญ่อนุญาตให้คุณรวมชุดคำสั่งเข้าในรายการ; ด้วยวิธีนี้ คุณสามารถไปป์งานจากทีมหนึ่งไปยังอีกทีมหนึ่งหรือเปลี่ยนเส้นทางไปในทางอื่นได้ โดยทั่วไปคุณสามารถทำได้โดยการรันรายการคำสั่งในเชลล์สำรองหรือเชลล์ปัจจุบัน

การรันรายการคำสั่งในเชลล์เพิ่มเติม

ใช้วงเล็บเพื่อรวมรายการคำสั่งไว้ในกลุ่มเดียว สิ่งนี้ทำให้คุณสามารถรันคำสั่งในเชลล์เพิ่มเติมและเปลี่ยนเส้นทางหรือรวบรวมเอาต์พุตดังที่แสดงในตัวอย่างต่อไปนี้:

รายการ 11. ตัวอย่างของแนวปฏิบัติที่ดี #6: การรันรายการคำสั่งในเชลล์เพิ่มเติม
~ $ (ซีดี tmp/a/b/c/ || mkdir -p tmp/a/b/c && \ > VAR=$PWD; cd ~; tar xvf -C $VAR archive.tar) \ > | ผู้ดูแลระบบ mailx -S "เนื้อหาที่เก็บถาวร"

ตัวอย่างนี้แยกเนื้อหาของไฟล์เก็บถาวรไปยังไดเร็กทอรี tmp/a/b/c ในขณะที่เอาต์พุตของคำสั่งที่จัดกลุ่ม รวมถึงรายการไฟล์ที่แตกออกมา จะถูกส่งไปที่ ที่อยู่ของผู้ดูแลระบบ.

การใช้ wrapper เพิ่มเติมจะมีประโยชน์ในกรณีที่คุณแทนที่ ตัวแปรสภาพแวดล้อมในรายการคำสั่งและไม่ต้องการยอมรับการเปลี่ยนแปลงเหล่านั้นในเชลล์ปัจจุบันของคุณ

รันรายการคำสั่งในเชลล์ปัจจุบัน

ใช้เครื่องหมายปีกกา (()) เพื่อใส่รายการคำสั่งที่จะเรียกใช้ ปัจจุบันเปลือก. ตรวจสอบให้แน่ใจว่าคุณเพิ่มช่องว่างระหว่างวงเล็บและคำสั่งเพราะ... มิฉะนั้น เชลล์อาจตีความวงเล็บไม่ถูกต้อง นอกจากนี้ ตรวจสอบให้แน่ใจว่าคำสั่งสุดท้ายในรายการตามด้วยอัฒภาค (;) ดังตัวอย่างต่อไปนี้:

รายการ 12. อีกตัวอย่างหนึ่งของแนวปฏิบัติที่ดี #6: การรันรายการคำสั่งในเชลล์ปัจจุบัน
~ $ ( cp $(VAR)a . && chown -R guest.guest a && \ > tar cvf newarchive.tar a; ) | ผู้ดูแลระบบ mailx -S "ไฟล์เก็บถาวรใหม่"

ใช้ xargs เพื่อค้นหาผลการค้นหา

ใช้คำสั่ง xargs เป็นตัวกรองเพื่อทำงานกับรายการไฟล์ที่ส่งคืนโดยการค้นหาด้วยคำสั่ง find โดยทั่วไปคำสั่ง find จะส่งคืนรายการไฟล์ที่ตรงกับเกณฑ์บางอย่าง รายการนี้ถูกส่งไปยัง xargs ซึ่งดำเนินการอื่นๆ โดยใช้รายการไฟล์เป็นอาร์กิวเมนต์ ดังตัวอย่างต่อไปนี้:

รายการ 13. ตัวอย่างการใช้คำสั่ง xargs แบบคลาสสิก
~$ ค้นหา | \>xargs

อย่างไรก็ตาม อย่าคิดว่า xargs เป็นเพียงส่วนเพิ่มเติมที่จะ find ; นี่เป็นหนึ่งในเครื่องมือเหล่านั้นที่เมื่อคุณคุ้นเคยแล้ว คุณจะต้องใช้งานมันอย่างต่อเนื่อง ตัวอย่างเช่น ในกรณีต่อไปนี้:

ผ่านรายการโดยคั่นด้วยช่องว่าง

ในภาพประกอบง่ายๆ นี้ xargs เปรียบเสมือนตัวกรองที่ใช้เป็นอินพุตรายการ (แต่ละองค์ประกอบบนบรรทัดที่แยกจากกัน) และวางองค์ประกอบไว้ในบรรทัดเดียวโดยคั่นด้วยช่องว่าง:

รายการ 14. ตัวอย่างเอาต์พุตของคำสั่ง xargs
~ $ xargsabc abc ~ $

คุณสามารถส่งเอาต์พุตของเครื่องมือใดๆ ที่ส่งออกชื่อไฟล์ผ่าน xargs เพื่อรับรายการอาร์กิวเมนต์ไปยังเครื่องมืออื่นๆ ที่ใช้ชื่อไฟล์เป็นอาร์กิวเมนต์ ดังตัวอย่างต่อไปนี้:

รายการ 15. ตัวอย่างการใช้คำสั่ง xargs
~/tmp $ ls -1 | xargs December_Report.pdf อ่านไฟล์ archive.tar mkdirhier.sh ~/tmp $ ls -1 | ไฟล์ xargs December_Report.pdf: เอกสาร PDF เวอร์ชัน 1.3 README: ข้อความ ASCII a: ไดเรกทอรี archive.tar: ไฟล์เก็บถาวร POSIX tar mkdirhier.sh: ข้อความสคริปต์เชลล์เป้าหมายที่เรียกใช้งานได้ ~/tmp $

คำสั่ง xargs มีประโยชน์มากกว่าแค่การส่งชื่อไฟล์ ใช้ทุกครั้งที่คุณต้องการกรองข้อความเป็นบรรทัดเดียว:

รายการ 16. ตัวอย่างแนวปฏิบัติที่ดี #7: การใช้เครื่องมือ xargs เพื่อกรองข้อความให้เป็นบรรทัดเดียว
~/tmp $ ls -l | xargs -rw-r--r-- 7 joe joe 12043 27 ม.ค. 20:36 ธันวาคม_Report.pdf -rw-r--r-- 1 \ root root 238 ธ.ค. 03 08:19 README drwxr-xr-x 38 joe joe 354082 02 พ.ย. \ 16:07 a -rw-r--r-- 3 joe joe 5096 14 ธ.ค. 14:26 archive.tar -rwxr-xr-x 1 \ joe joe 3239 30 ก.ย. 12:40 mkdirhier.sh ~/ ทีเอ็มพี$

ระวังเมื่อใช้ xargs

ในทางเทคนิคแล้ว มีกรณีที่ไม่ค่อยเกิดขึ้นที่การใช้ xargs อาจเป็นปัญหาได้ ตามค่าเริ่มต้น อักขระท้ายไฟล์จะเป็นขีดล่าง (_) หากอักขระตัวนี้ถูกส่งเป็นอาร์กิวเมนต์เดียว ทุกอย่างหลังจากนั้นจะถูกละเว้น เพื่อเป็นการป้องกันไว้ก่อน ให้ใช้แฟล็ก -e ซึ่งจะปิดใช้งานอักขระส่วนท้ายของไฟล์โดยไม่มีอาร์กิวเมนต์

รู้ว่าเมื่อใดควรใช้ grep ในการนับ - และเมื่อใดที่ควรหลีกเลี่ยง

หลีกเลี่ยงการใช้ wc -l หลังจาก grep เพื่อนับจำนวนบรรทัดที่ได้รับ ตัวเลือก -c เพื่อ grep ช่วยให้คุณสามารถนับจำนวนบรรทัดที่ตรงกับรูปแบบที่กำหนด และโดยทั่วไปจะเร็วกว่าชุดค่าผสม "wc หลัง grep" ดังตัวอย่างต่อไปนี้:

รายการ 17. ตัวอย่างวิธีการทำงานที่ดี #8: การนับจำนวนบรรทัดที่มีและไม่มี grep
~ $ เวลา grep และ tmp/a/longfile.txt | wc -l 2811 ผู้ใช้จริง 0m0.097s 0m0.006s sys 0m0.032s ~ $ เวลา grep -c และ tmp/a/longfile.txt 2811 ผู้ใช้จริง 0m0.013s 0m0.006s sys 0m0.005s ~ $

ตัวเลือก -c คือ ในทางที่ดีการนับไม่ได้เกิดจากปัจจัยด้านความเร็วเท่านั้น เมื่อใช้หลายไฟล์ grep พร้อมด้วยตัวเลือก -c จะส่งกลับค่าที่แยกจากกันสำหรับแต่ละไฟล์ หนึ่งไฟล์ในแต่ละบรรทัด ในขณะที่ทิศทางเอาต์พุตใน wc ให้ ผลลัพธ์โดยรวมสำหรับไฟล์ทั้งหมด

อย่างไรก็ตาม ตัวอย่างนี้น่าสนใจไม่เพียงแต่จากมุมมองของประสิทธิภาพเท่านั้น แต่ยังแสดงให้เห็นถึงข้อผิดพลาดทั่วไปอีกประการหนึ่งอีกด้วย วิธีการนับนี้มีให้เท่านั้น จำนวนบรรทัดที่พบตรงกับรูปแบบ- และดีถ้านั่นคือสิ่งที่คุณกำลังมองหา แต่ในกรณีที่สตริงอาจมีหลายรายการที่ตรงกันกับรูปแบบใดรูปแบบหนึ่ง วิธีการเหล่านี้จะไม่ให้ข้อมูลจริงใดๆ จำนวนรายการที่ตรงกับรูปแบบ- หากต้องการนับจำนวนการแข่งขัน ให้ใช้ wc ในการเริ่มต้น ให้รัน grep ด้วยตัวเลือก -o หากเวอร์ชันของคุณรองรับ ตัวเลือกนี้จะปรากฏขึ้น เท่านั้นจับคู่รูปแบบ หนึ่งรายการสำหรับแต่ละบรรทัด แต่ไม่ใช่บรรทัดนั้นเอง ไม่สามารถใช้กับตัวเลือก -c ได้ ดังนั้นให้ใช้ wc -l เพื่อนับจำนวนบรรทัด ดังตัวอย่างต่อไปนี้:

ตัวอย่างแนวปฏิบัติที่ดี #8: การนับจำนวนรายการที่ตรงกันกับรูปแบบด้วย grep
~ $ grep -o และ tmp/a/longfile.txt | สุขา -l 3402 ~ $

ในกรณีนี้ การเรียก wc จะเร็วกว่าการเรียก grep ครั้งที่สองเล็กน้อยด้วยรูปแบบจำลองเพื่อให้สามารถเปรียบเทียบและนับแต่ละบรรทัดได้ (เช่น grep -c)

การเปรียบเทียบฟิลด์เอาต์พุตเฉพาะ ไม่ใช่แค่สตริง

เครื่องมืออย่าง awk เหมาะกว่า grep เมื่อคุณต้องการจับคู่รูปแบบเฉพาะใน สาขาเฉพาะบรรทัดเอาต์พุต ไม่ใช่ทั้งบรรทัด

ตัวอย่างอย่างง่ายต่อไปนี้แสดงวิธีจัดเรียงเฉพาะไฟล์ที่มีการเปลี่ยนแปลงในเดือนธันวาคม:

รายการ 19. ตัวอย่างการปฏิบัติที่ไม่ดี #9: การใช้ grep เพื่อค้นหารูปแบบในสาขาเฉพาะ
~/tmp $ ls -l /tmp/a/b/c | grep Dec -rw-r--r-- 7 joe joe 12043 27 ม.ค. 20:36 ธันวาคม_Report.pdf -rw-r--r-- 1 รูทรูท 238 ธ.ค. 03 08:19 README -rw-r--r- - 3 โจโจ 5,096 14 ธันวาคม 14:26 archive.tar ~/tmp $

ในตัวอย่างนี้ grep กรองบรรทัดและพิมพ์ไฟล์ทั้งหมดที่มี Dec ในชื่อหรือวันที่แก้ไข ดังนั้นไฟล์เช่น December_Report.pdf ก็ใช้ได้แม้ว่าจะไม่มีการแก้ไขตั้งแต่เดือนมกราคมก็ตาม นี่อาจไม่ใช่สิ่งที่คุณต้องการ หากต้องการจับคู่รูปแบบในฟิลด์เฉพาะ ควรใช้ awk ซึ่งตัวดำเนินการสัมพัทธ์จะตรงกับฟิลด์เฉพาะ ดังที่แสดงในตัวอย่างต่อไปนี้

รายการ 20 ตัวอย่างวิธีแก้ปัญหาที่ดี #9: การใช้ awk เพื่อค้นหารูปแบบในฟิลด์เฉพาะ
~/tmp $ ls -l | awk "$6 == "Dec"" -rw-r--r-- 3 joe joe 5096 14 ธันวาคม 14:26 archive.tar -rw-r--r-- 1 รูทรูท 238 ธันวาคม 03 ธันวาคม 08:19 README ~ /tmp$

รายละเอียดเพิ่มเติมเกี่ยวกับ ใช้ awkสามารถอ่านได้ในส่วน

อย่าใช้การส่งผ่านเอาต์พุต cat

ข้อผิดพลาดพื้นฐานและทั่วไปในการใช้ grep คือการส่งเอาต์พุตของ cat ไปยัง grep เพื่อค้นหาเนื้อหาของไฟล์เดียว นี่เป็นการเสียเวลาโดยไม่จำเป็นโดยสิ้นเชิง เนื่องจากเครื่องมืออย่าง grep ใช้ชื่อไฟล์เป็นอาร์กิวเมนต์ ดังนั้นจึงไม่จำเป็นต้องใช้ cat ในสถานการณ์นี้อย่างแน่นอน ดังตัวอย่างต่อไปนี้:

รายการ 21. ตัวอย่างวิธีการที่ดี #10: การใช้ grep แบบมีและไม่มี cat
~ $ เวลา cat tmp/a/longfile.txt | grep และ 2811 ผู้ใช้ 0m0.015s จริง 0m0.003s sys 0m0.013s ~ $ เวลา grep และ tmp/a/longfile.txt 2811 ผู้ใช้ 0m0.010s จริง 0m0.006s sys 0m0.004s ~ $

ข้อผิดพลาดนี้เกิดขึ้นในหลายกรณี เนื่องจากเครื่องมือส่วนใหญ่ใช้อินพุตมาตรฐานเป็นอาร์กิวเมนต์โดยใช้เครื่องหมายขีดกลาง (-) แม้แต่อาร์กิวเมนต์สำหรับการใช้ cat เพื่อกระจายไฟล์จำนวนมากด้วย stdin ก็มักจะไม่ถูกต้อง จริงๆแล้วจำเป็นต้องต่อข้อมูลกันก่อน ใช้แมวด้วยหนึ่งในตัวเลือกการกรองที่หลากหลาย

สรุป: ทำความคุ้นเคยกับสิ่งที่ดี

เราดูหลายวิธีในการทำงานบนบรรทัดคำสั่ง นิสัยที่ไม่ดีทำให้งานของคุณช้าลงและมักนำไปสู่ข้อผิดพลาดที่ไม่คาดคิด บทความนี้จะแชร์เทคนิคใหม่ 10 ประการที่สามารถช่วยคุณกำจัดข้อผิดพลาดที่พบบ่อยที่สุดได้ ทำความคุ้นเคยกับเทคนิคดีๆ เหล่านี้และพัฒนาทักษะการจัดการของคุณ บรรทัดคำสั่งยูนิกซ์

xargs- ยูทิลิตี้สำหรับสร้างรายการอาร์กิวเมนต์และดำเนินการคำสั่ง นั่นคือ xargs ให้คุณเรียกใช้คำสั่งใดๆ พร้อมอาร์กิวเมนต์ได้ คำสั่ง xargs มีสององค์ประกอบ ขั้นแรกคุณต้องระบุไฟล์ที่คุณสนใจ ประการที่สอง คุณต้องระบุคำสั่งหรือสคริปต์ที่คุณต้องการใช้กับแต่ละไฟล์เหล่านี้

xargs - แยกอินพุตสตรีมออกเป็นอาร์กิวเมนต์และส่งผ่านการดำเนินการไปยังคำสั่งใด ๆ (สะท้อนโดยค่าเริ่มต้น) อ่านได้จาก. อินพุตมาตรฐานหรือทางท่อ

โหมดการประมวลผล xargs สำหรับข้อมูลขาเข้า

    ตามค่าเริ่มต้น ตัวแยกอาร์กิวเมนต์คืออักขระช่องว่าง: ช่องว่าง แท็บ แท็บแนวตั้ง หรือการขึ้นบรรทัดใหม่ แต่เช่นเดียวกับในเชลล์คำสั่ง คุณสามารถใช้ "" หรือ \ เพื่อป้องกันการแยกอาร์กิวเมนต์

    โหมดเปิดใช้งานโดยพารามิเตอร์ -L เกือบจะเหมือนกันกับอันก่อนหน้า ยกเว้นว่า xargs จะจดจำอาร์กิวเมนต์ใดอยู่บนบรรทัดใด นอกจากนี้ หากบรรทัดลงท้ายด้วยช่องว่างหรือแท็บ บรรทัดถัดไปจะถือเป็นบรรทัดต่อจากบรรทัดปัจจุบัน

    ทีละบรรทัด เปิดใช้งานเมื่อใช้ตัวเลือก -I หรือ -0 ในกรณีนี้ สตริงทั้งหมดจะถือเป็นอาร์กิวเมนต์ทั้งหมด 1 รายการ แม้ว่าจะมีช่องว่างและแท็บอยู่ข้างในก็ตาม สำหรับ -I ท้ายบรรทัดคืออักขระ "\n" และสำหรับ -0 อักขระ "\0"

    ตัวอย่าง: ค้นหา /home/user1 สำหรับไฟล์ทั้งหมดที่มีชื่อลงท้ายด้วย ".txt" และคัดลอกไปยังไดเร็กทอรีอื่น ค้นหา /home/user1 -name "*.txt" | xargs cp -av --target-directory=/home/backup/ --parents

    ค้นหาวลี Logon Home ในไฟล์ทั้งหมดที่อยู่ในไดเร็กทอรี /etc/samba $ ค้นหา /etc/samba | xargs grep -ni "เข้าสู่ระบบหน้าแรก"

    ลบรายการไฟล์ เส้นทางของไฟล์จะถูกเขียนทีละบรรทัดในไฟล์ delfiles.txt xargs rm< delfiles.txt

มีการเขียนมากมายเกี่ยวกับยูทิลิตี้ xargs - มีอะไรให้เขียนอีกบ้าง? แต่ถ้าคุณเจาะลึกอย่างที่พวกเขาพูด ปรากฎว่าสิ่งพิมพ์จำนวนมากสรุปเฉพาะพื้นฐานเท่านั้น แต่ขาดสิ่งสำคัญ: พวกเขาไม่ได้อธิบายว่า xargs สามารถนำมาใช้ในทางปฏิบัติได้อย่างไร น่าเสียดายที่มีบทความเพียงไม่กี่บทความที่วิเคราะห์ตัวเลือกที่ซับซ้อนและไม่สำคัญสำหรับการใช้เครื่องมือนี้ ซึ่งมีประโยชน์มากสำหรับผู้ดูแลระบบ นั่นคือเหตุผลที่เราเขียนบทความของเราและพยายามรวมตัวอย่างการใช้ xargs เพื่อแก้ไขปัญหาต่างๆ ให้ได้มากที่สุด

ขั้นแรก เราจะดูว่า xargs ทำงานอย่างไรและวิเคราะห์ตัวอย่างที่ง่ายกว่า จากนั้นจึงไปยังการวิเคราะห์กรณีที่ซับซ้อนและน่าสนใจ

เรามาจำพื้นฐานกัน

วิธีการทำงานของ xargs สามารถอธิบายได้ดังต่อไปนี้: โปรแกรมรับข้อมูลจากอินพุตมาตรฐานหรือจากไฟล์ แล้วแยกตามพารามิเตอร์ที่ระบุ จากนั้นส่งต่อไปยังโปรแกรมอื่นเป็นอาร์กิวเมนต์

โดยทั่วไป ไวยากรณ์ของคำสั่ง xargs สามารถแสดงได้ดังต่อไปนี้:

[list_generator_command] | xargs [xargs_options] [คำสั่ง]
มาดูวิธีการทำงานทั้งหมดโดยใช้ตัวอย่างง่ายๆ และในตำราเรียน

กำลังลบไฟล์

หนึ่งในสถานการณ์ทั่วไปที่ใช้ xargs คือการลบไฟล์ที่พบโดยใช้คำสั่ง find

ลองจินตนาการถึงสถานการณ์ต่อไปนี้: มีไดเร็กทอรีอยู่ จำนวนมากไฟล์. คุณต้องลบไฟล์ออกจากมัน บางประเภท(ในตัวอย่างของเรา - ไฟล์ที่มีนามสกุล *.sh) ในการดำเนินการนี้ คุณต้องส่งเอาต์พุตของคำสั่ง find ไปยัง xargs และคำสั่ง -rm จะถูกนำไปใช้กับไฟล์ที่มีนามสกุลที่ระบุ:

$ ls one.sh one.py two.sh two.py $ ค้นหา -ชื่อ "*.sh"| xargs rm -rf $ ls one.py two.py

โปรดทราบว่าการดำเนินการลบไฟล์สามารถทำได้โดยไม่ต้องใช้ xargs แต่ใช้คำสั่ง

$ ค้นหา -ชื่อ "*.sh" -exec rm -rf "()" \

วิธีการที่อธิบายไว้จะไม่ทำงานหากชื่อของไฟล์ใดไฟล์หนึ่งที่จะลบมีช่องว่าง ชื่อที่ประกอบด้วยคำสองคำคั่นด้วยช่องว่างจะไม่ได้รับการยอมรับโดยรวม

เรามาอธิบายสิ่งนี้ด้วยตัวอย่างต่อไปนี้:

$ ls ไฟล์ใหม่ sh one.sh one.py two.sh two.py $ find -ชื่อ "*.sh"| xargs rm -rf $ ls ใหม่ file.sh one.py two.py

อย่างที่คุณเห็นไฟล์ที่มีช่องว่างในชื่อจะไม่ถูกลบ

เพื่อแก้ไขปัญหานี้ ให้ใช้อ็อพชัน print0 สำหรับคำสั่ง find และอ็อพชัน -0 สำหรับคำสั่ง xargs โดยแทนที่ตัวคั่นมาตรฐาน (ตัวแบ่งบรรทัดด้วยอักขระ null (\x0) ซึ่งหมายถึงจุดสิ้นสุดของสตริงที่เก็บไว้:

$ ค้นหา -ชื่อ "*.sh" -print0 | xargs -0 rm -rf

Xargs ยังสามารถช่วยได้ เช่น ลบทุกสิ่งอย่างรวดเร็ว ไฟล์ชั่วคราวด้วยส่วนขยาย tmp:

$ ค้นหา /tmp -name "*.tmp"| xargs rm

การบีบอัดไฟล์

คุณสามารถบีบอัดไฟล์ทั้งหมดในไดเร็กทอรีปัจจุบันโดยใช้ gzip โดยการป้อนคำสั่งต่อไปนี้:

$ls | xargs -p -l gzip

ลองดูตัวอย่างอื่น: บีบอัดไฟล์ทั้งหมดที่มีนามสกุล *.pl โดยใช้ tar:

$ ค้นหา -ชื่อ "*.pl" | xargs tar -zcf pl.tar.gz

การเปลี่ยนชื่อไฟล์

ด้วย xargs คุณสามารถทำได้ การเปลี่ยนชื่อจำนวนมากไฟล์. สมมติว่าเรามีกลุ่มไฟล์ที่มีนามสกุล *.txt และเราจำเป็นต้องแทนที่นามสกุลนี้ด้วย *.sql ซึ่งสามารถทำได้โดยใช้ xargs และการสตรีมข้อความ บรรณาธิการ sed:

$ls | sed -e "p;s/.txt$/.sql/" | xargs -n2 เอฟเอ็มวี

จากการดำเนินการ รายการไฟล์ที่ถูกเปลี่ยนชื่อจะปรากฏบนคอนโซล

ด้วย xargs คุณสามารถเพิ่มเข้าไปได้ องค์ประกอบเพิ่มเติมไปยังชื่อไฟล์ (เช่น วันที่):

$ls | xargs -I ไฟล์ mv()<...>-{}

แทน<..>คุณสามารถทดแทนสิ่งที่คุณต้องการได้
วงเล็บปีกกา () ในตัวอย่างนี้หมายถึง "อาร์กิวเมนต์ปัจจุบัน" (นั่นคือชื่อไฟล์ปัจจุบัน)

การเปลี่ยนการอนุญาตสำหรับโฟลเดอร์และไฟล์

การใช้ xargs ช่วยให้คุณสามารถเร่งกระบวนการเปลี่ยนสิทธิ์ในไฟล์และโฟลเดอร์ได้ ผู้ใช้เฉพาะหรือกลุ่ม สมมติว่าเราจำเป็นต้องค้นหาโฟลเดอร์ทั้งหมด ผู้ใช้รูทและแทนที่เจ้าของด้วยอุณหภูมิ การดำเนินการนี้ดำเนินการโดยใช้คำสั่ง:

$ ค้นหา -group root -พิมพ์ | xargs อุณหภูมิ chunk

หากต้องการค้นหาโฟลเดอร์ทั้งหมดของกลุ่มรูทและแทนที่กลุ่มด้วย temp ให้ใช้คำสั่ง:

$ ค้นหา -group root -พิมพ์ | xargs chgrp อุณหภูมิ

Xargs และค้นหา: การดำเนินการที่ซับซ้อน

คุณสามารถดำเนินการที่ซับซ้อนมากขึ้นได้โดยใช้คำสั่ง find และ xargs ตัวอย่างเช่น คุณสามารถลบไฟล์ชั่วคราวที่สร้างขึ้นเกิน 7 วันที่ผ่านมาได้ดังนี้:

$ find /tmp -type f -name "*" -mtime +7 -print0 | xargs -0 rm -f

และนี่คือวิธีบังคับหยุดกระบวนการที่ทำงานมานานกว่า 7 วันโดยเด็ดขาด:

$ find /proc -user myuser -maxdeep 1 -type d -mtime +7 -exec basename() \; - xargs ฆ่า -9

Xargs และตัด

Xargs มักใช้ร่วมกับคำสั่ง cut ซึ่งช่วยให้คุณสามารถตัดบรรทัดได้ ไฟล์ข้อความ- มาดูกันบ้างครับ ตัวอย่างการปฏิบัติ- เมื่อใช้คำสั่งด้านล่าง รายชื่อผู้ใช้ทั้งหมดในระบบจะแสดงบนคอนโซล:

$ ตัด -d: -f1< /etc/passwd | sort | xargs echo

และทีมงานก็ดู

ไฟล์ * | grep ASCII | ตัด -d:: -f1 | xargs -p เป็นกลุ่ม
จะเปิดไฟล์ตามลำดับเพื่อแก้ไขเป็นกลุ่ม
มาดูตัวเลือก -p กันดีกว่า ด้วยเหตุนี้คำสั่งจึงจะถูกดำเนินการ โหมดโต้ตอบ: จะมีการร้องขอการยืนยัน (y/n) ก่อนเปิดแต่ละไฟล์

โดยสรุปนี่คืออีกสิ่งที่ซับซ้อนและ ตัวอย่างที่น่าสนใจ— การค้นหาไฟล์ที่ใหญ่ที่สุดในไดเร็กทอรีหนึ่ง ๆ แบบเรียกซ้ำ:

$ ค้นหา -พิมพ์ f -printf "%20s %p\n" | เรียงลำดับ -n | ตัด -b22- | tr "\n" "\000" | xargs -0 ls -laSr

การทำงานแบบขนานของกระบวนการ

Xargs มักใช้เพื่อรันหลายกระบวนการพร้อมกัน นี่คือวิธีที่คุณสามารถบีบอัดหลายไดเร็กทอรีลงใน tar.gz พร้อม ๆ กัน:

$ echo dir1 dir2 dir3 | xargs -P 3 -ฉันชื่อ tar czf NAME.tar.gz NAME

ตัวอย่างด้านล่างใช้สวิตช์ -P เขาชี้ ปริมาณสูงสุดกระบวนการที่จะทำงานพร้อมกัน สมมติว่าเรามี 10 อาร์กิวเมนต์เป็นอินพุต หากเราป้อนคำสั่ง xargs ด้วยสวิตช์ -P 3 ดังนั้น 3 อินสแตนซ์ของคำสั่งที่ตามหลัง xargs จะถูกเรียกใช้ โดยแต่ละอาร์กิวเมนต์เหล่านี้

ด้วย xargs คุณสามารถดาวน์โหลดไฟล์หลายไฟล์จากอินเทอร์เน็ตพร้อมกันได้:

ในตัวอย่างที่กำหนดด้วย ที่อยู่ที่ระบุทั้งหมดจะถูกดาวน์โหลด ไฟล์กราฟิกกับ นามสกุล.jpg- สวิตช์ -P ระบุว่าคุณต้องดาวน์โหลดไฟล์ครั้งละ 10 ไฟล์

ผลเบื้องต้น

มาสรุปผลลัพธ์เบื้องต้นและกำหนดกฎสองสามข้อสำหรับการทำงานกับ xargs

  1. Xargs ไม่ทำงานกับไฟล์ที่มีช่องว่างในชื่อ หากต้องการแก้ไขปัญหานี้ด้วยคำสั่ง xargs ให้ใช้ตัวเลือก −0 คุณสามารถข้ามช่องว่างในชื่อไฟล์ได้ดังนี้:
    $ xargs -I FILE my_command “ไฟล์”
  2. คำสั่ง xargs ยอมรับคำสั่งจากอินพุตมาตรฐาน โดยคั่นด้วยช่องว่างหรือขึ้นบรรทัดใหม่ หากต้องการจัดกลุ่มคำสั่งเหล่านี้ คุณสามารถใช้ double หรือ คำพูดเดียว- คุณยังสามารถระบุตัวคั่นได้โดยใช้ตัวเลือก -d
  3. หากไม่มีการส่งอาร์กิวเมนต์ไปที่ xargs คำสั่ง /bin/echo จะถูกดำเนินการตามค่าเริ่มต้น
  4. ในหลายกรณี คำสั่ง xargs สามารถแทนที่ด้วย for loop ได้ เช่น คำสั่ง
    $ ค้นหา -พิมพ์ f -และ -iname "*.deb" | xargs -n 1 dpkg -I
    เทียบเท่ากับวัฏจักรโดยสมบูรณ์
    $ สำหรับไฟล์ใน `ค้นหา -พิมพ์ f -และ -iname "*.deb"`; ทำ dpkg -I "$file"; เสร็จแล้ว

ตัวอย่างที่ไม่สำคัญ

เราจำพื้นฐานได้ ตัวเลือกทั่วไปใช้การพิจารณาแล้ว... ตอนนี้เรามาดูตัวอย่างที่ซับซ้อนและไม่สำคัญมากขึ้นกันดีกว่า เราคิดขึ้นมาเองบางส่วนในขณะที่ทำงานในชีวิตประจำวันและบางส่วนเราเรียนรู้จากเว็บไซต์ http://www.commandlinefu.com (เราขอแนะนำอย่างยิ่งให้ทุกคนที่ต้องการเรียนรู้ความซับซ้อนของการทำงานกับบรรทัดคำสั่ง เยี่ยมชมเป็นครั้งคราว - บางครั้งคุณอาจพบว่ามีมาก เคล็ดลับที่เป็นประโยชน์).

ห้ามที่อยู่ IP จากรายการ

หากต้องการแบนที่อยู่ IP จากรายการ คุณต้องเพิ่มที่อยู่ IP ลงในตาราง IP ด้วยกฎ DROP การดำเนินการนี้ดำเนินการโดยใช้คำสั่ง:

$ แมว bad_ip_list | xargs -I IP iptables -A INPUT -s IP -j DROP
คุณยังสามารถดำเนินการที่ซับซ้อนมากขึ้นและแบนที่อยู่ทั้งหมดตาม AS:

$ /usr/bin/whois -H -h whois.ripe.net -T เส้นทาง -i ต้นกำเนิด AS<номер>|egrep "^route"|awk "(พิมพ์ $2)" |xargs -I NET iptables -A INPUT -s NET -j DROP

การเปลี่ยนรูปแบบ URL

คุณสามารถแปลง URL เช่น “http%3A%2F%2Fwww.google.com” เป็น “www ,google.com” โดยใช้คำสั่ง:

ก้อง "http%3A%2F%2Fwww.google.com" | sed -e"s/%\(\)/\\\\\x\1/g" | xargs เสียงสะท้อน -e

การสร้างรหัสผ่าน 10 ตัวอักษร

สร้าง รหัสผ่านที่แข็งแกร่งสามารถทำได้โดยใช้คำสั่งเช่น:

$ tr -dc A-Za-z0-9_< /dev/urandom | head -c 10 | xargs

คุณสามารถสร้างรหัสผ่านโดยไม่ต้องใช้ xargs: มียูทิลิตี้เฉพาะสำหรับสิ่งนี้ pwgen มีการอธิบายวิธีการอื่นๆ บางประการในการสร้างรหัสผ่านด้วย

ค้นหาไบนารีที่ติดตั้งโดยไม่ใช้ dpkg

การดำเนินการดังกล่าวอาจจำเป็น ตัวอย่างเช่น หากเครื่องตกเป็นเหยื่อของการโจมตีของแฮ็กเกอร์และมีการติดตั้งซอฟต์แวร์ที่เป็นอันตรายไว้ ซอฟต์แวร์- คำสั่งต่อไปนี้จะช่วยคุณระบุโปรแกรมที่ผู้โจมตีติดตั้งไว้ (มองหาการเรียกใช้ "ไบนารี" ที่ติดตั้งโดยไม่ต้องใช้ตัวจัดการแพ็คเกจ dpkg):

$ cat /var/lib/dpkg/info/*.list > /tmp/listin ; ls /proc/*/exe |xargs -l readlink | grep -xvFf /tmp/listin; rm /tmp/listin.rm

การลบแพ็คเกจเคอร์เนลที่ล้าสมัย

$ dpkg -l linux-* | awk "/^ii/( พิมพ์ $2)" | grep -v -e `uname -r | ตัด -f1,2 -d"-"` | grep -e | xargs sudo apt-get -y ล้างข้อมูล

ปัญหาในการลบเมล็ดเก่าได้ถูกกล่าวถึงในHabréแล้ว - ดู (ที่ลิงค์เดียวกันคุณสามารถดูตัวอย่างคำสั่งที่น่าสนใจได้)

การแปลงสคริปต์เป็นสตริง

บางครั้งจำเป็นต้องแปลงสคริปต์ขนาดใหญ่ให้เป็นบรรทัดเดียว คุณสามารถทำได้เช่นนี้:

  • เลือก
  • เลือก
  • เพิ่มแท็ก

    มีคำสั่งที่แปลกมากใน Linux xargs ซึ่งกูรูคนไหนชื่นชอบมากแต่ก็ไม่รีบร้อนที่จะอธิบายวิธีการทำงาน อินเทอร์เน็ตเต็มไปด้วยสูตรอาหารเกี่ยวกับ "วิธีใช้ xargs" แต่ไม่มีสูตรใดระบุสิ่งที่สำคัญที่สุดอย่างชัดเจน: คำสั่งนี้ทำอะไรได้จริง

    ที่สำคัญที่สุด

    โดยทั่วไปแล้ว สิ่งเดียวกันนี้จะถูกเขียนทุกที่: คำสั่ง xargs รับอินพุตสตรีม (ซึ่งเป็นสาเหตุที่คำสั่งบางคำสั่งและสัญลักษณ์การเปลี่ยนเส้นทางสตรีม "|") นำหน้าเสมอ และด้วยไวยากรณ์วิเศษบางอย่างที่รันคำสั่งที่ระบุในนั้น .

    นี่คือสิ่งที่คำสั่ง xargs ทำจริง(ฉันจะพยายามกำหนดให้เป็นกลางที่สุด) มันทำลายกระแสของสัญลักษณ์ที่ส่งเข้ามาเป็นชิ้น ๆ ใช้อักขระตัวคั่นเพื่อแยกสตรีม และสำหรับแต่ละชิ้นส่วนที่เลือก มันจะรันคำสั่งที่ระบุไว้ทางด้านขวา เสริมคำสั่งนี้ทางด้านขวาด้วยสัญลักษณ์ของชิ้นส่วนที่พบ

    ใช่ คำจำกัดความนี้ใช้แนวคิดเรื่อง "ถูกต้อง" สองครั้ง รายละเอียดอธิบายไว้ด้านล่าง ในระหว่างนี้ ควรดูโครงสร้างของคำสั่ง xargs ในรูปแบบรูปภาพจะดีกว่า ในทางวากยสัมพันธ์ คำสั่ง xargs ประกอบด้วยสองส่วน - ซ้ายและขวา:

    ยิ่งไปกว่านั้น ยังมีการแยกภาพอย่างชัดเจนว่าอยู่ที่ไหนและอยู่ที่ไหน ด้านขวาแค่ไม่ หากคุณกำลังพยายามทำความเข้าใจคำสั่ง xargs ของบุคคลอื่น คุณจะต้องค้นหา "อินเทอร์เฟซ" นี้ด้วยตนเอง นี่คือตัวอย่างบางส่วน:

    ครบทีม

    ด้านซ้าย

    ด้านขวา

    บันทึก

    xargs rm -rf

    xargs

    RM-RF

    xargs -0 rm -rf

    xargs -0

    RM-RF

    xargs -p -l gzip

    xargs -p -l

    gzip

    xargs tar -zcf pl.tar.gz

    xargs

    tar -zcf pl.tar.gz

    xargs -n2 เอฟเอ็มวี

    xargs -n2

    xargs -I ไฟล์ mv

    ไฟล์ xargs -I

    ใช่ไม่มีข้อผิดพลาดที่นี่

    xargs อุณหภูมิ chunk

    xargs

    อุณหภูมิโชว

    xargs ฆ่า -9

    xargs

    ฆ่า -9

    xargs -p เป็นกลุ่ม

    xargs-p

    นั่นคือกฎจะใช้ที่นี่: หากหลังจาก xargs มีอักขระที่นำหน้าด้วยเครื่องหมายลบ"-" จากนั้นนี่คือตัวเลือกคำสั่ง xargs - ทันทีที่มีสัญลักษณ์ที่ไม่มีเครื่องหมายลบ แสดงว่าสัญลักษณ์เหล่านี้อยู่ทางด้านขวาแล้ว แต่คุณต้องคำนึงถึงตัวเลือกบางอย่างด้วย xargs ต้องการข้อมูลอื่นหลังจากนั้นซึ่งจะไม่มีเครื่องหมายลบนำหน้า (ดูตัวอย่างพร้อมตัวเลือก-ฉัน ).

    และตอนนี้สิ่งที่สำคัญที่สุด: มันรันคำสั่งอะไร? xargs - เธอผลักชุดสัญลักษณ์ที่เธอแยกออกจากสตรีมอินพุตที่ไหน ง่ายมาก: เธอวางสัญลักษณ์เหล่านี้ไว้ทางด้านขวาของคำสั่งที่เขียนไว้ทางด้านขวา ฉันเข้าใจว่าแนวคิดเรื่อง "ความถูกต้อง" ถูกใช้สองครั้งที่นี่ นี่คือภาพที่นำทุกอย่างเข้าที่:

    เอาล่ะ ตัวอย่างที่เป็นรูปธรรม- ไดเร็กทอรีประกอบด้วยไฟล์ต่อไปนี้:

    main.cpp

    main.h

    รุ่น.cpp

    รุ่น.h

    config.cpp

    config.h

    ข้อมูล.cpp

    ข้อมูล.h

    ภายในไดเร็กทอรีนี้คำสั่งจะถูกดำเนินการ:

    $ ค้นหา -ชื่อ "*.cpp" | xargs -n 1 rm -rf

    xargs จะสร้างคำสั่งอะไร? เพื่อตอบคำถามนี้ คุณต้องเข้าใจว่าอะไรจะถูกส่งไปให้กับข้อมูลของมัน และอินพุตจะเป็นผลลัพธ์ของคำสั่ง find:

    ./main.cpp

    ./version.cpp

    ./config.cpp

    ./data.cpp

    คำสั่ง xargs พิจารณาตัวคั่นช่องว่าง แท็บ หรือการป้อนบรรทัด (และลำดับต่อเนื่องกัน) ดังนั้นคำสั่งทั้งสี่จะถูกดำเนินการในตอนท้าย:

    RM -rf ./main.cpp

    RM -rf ./version.cpp

    RM -rf ./config.cpp

    RM -rf ./data.cpp

    มาก หมายเหตุสำคัญเกี่ยวกับตัวเลือกเวทย์มนตร์

    มีบันทึกที่สำคัญมากประการหนึ่ง หากคุณไม่เข้าใจ คุณจะไม่สามารถทำงานกับ xargs ได้อย่างถูกต้อง และคุณจะกลายเป็นเหมือนผู้เขียนบทความที่คิดว่าพวกเขาเข้าใจวิธีการทำงานของ xargs แต่จริงๆ แล้วเขียนเรื่องไร้สาระที่แย่มาก ในตัวอย่างข้างต้น ตัวเลือกถูกเขียนด้วยเหตุผล"-n1" .

    ตัวเลือก "-n 1" ทำให้ xargs ดำเนินการคำสั่งสำหรับแต่ละก้อนที่ต่อเนื่องกันจากสตรีมอินพุต ใช่ ฉันเข้าใจว่ามันฟังดูบ้าไปเลย เพราะท้ายที่สุดแล้ว ทีม xargs ควรจะทำเช่นนั้น! ท้ายที่สุดแล้วคู่มือบอกว่าต่อไปนี้:"xargs อ่านรายการจากอินพุตมาตรฐาน คั่นด้วยช่องว่าง (ซึ่งสามารถป้องกันด้วยเครื่องหมายคำพูดคู่หรือเดี่ยวหรือแบ็กสแลช) หรือขึ้นบรรทัดใหม่ และดำเนินการคำสั่ง (ค่าเริ่มต้นคือ /bin/echo) หนึ่งครั้งหรือมากกว่านั้นด้วยอาร์กิวเมนต์เริ่มต้นใดๆ ตามด้วยรายการที่อ่านจากอินพุตมาตรฐาน"ปัญหาคือว่าโดยค่าเริ่มต้นถ้าคุณไม่ระบุ"-n1" , xargs ถือว่าสตรีมขาเข้าทั้งหมด โดยแยกย่อยตามช่องว่าง แท็บ และการขึ้นบรรทัดใหม่ เป็นอาร์กิวเมนต์เดียว และในความเป็นจริง สตรีมที่เข้ามาทั้งหมดจะถูกแทนที่ด้วยคำสั่งที่กำลังดำเนินการ ช่างน่าประหลาดใจจริงๆจากนักพัฒนา!

    คำถาม: ตัวอย่างที่ให้ไว้ในบทความทำงานอย่างไร เช่น

    $ ค้นหา -ชื่อ "*.cpp" | xargs rm -rf

    $ ค้นหา -ชื่อ "*.cpp" | xargs wc -l

    และมันทำงานเพียงเพราะคำสั่งนั้นเอง RM ห้องน้ำ และโปรแกรมอื่นๆ ที่คล้ายกันสามารถทำงานกับชุดชื่อไฟล์ได้ และผู้ใช้เข้าใจผิดว่านี่คือ xargs เรียกคำสั่งเหล่านี้หลายครั้งสำหรับแต่ละชื่อไฟล์ และเพื่อให้แน่ใจว่าสิ่งนี้ คุณสามารถใช้ตัวเลือกนี้ได้-ที (พิมพ์คำสั่งที่สร้างขึ้น xargs ก่อนที่จะดำเนินการ) แต่หากต้องการดูผลลัพธ์ คุณยังคงต้องใช้โครงสร้างการเปลี่ยนเส้นทางเอาต์พุตจากสตรีมข้อผิดพลาด 2>&1 (เนื่องจากใช้ตัวเลือก-ที ให้เอาต์พุตไปยังสตรีมข้อผิดพลาดแทนที่จะเป็นคอนโซลมาตรฐาน) และนี่คือสิ่งที่คุณเห็น

    หากคุณเขียนคำสั่ง xargsโดยไม่มีตัวเลือก "-n 1" แล้วสิ่งต่อไปนี้จะเกิดขึ้น:

    $ ค้นหา -ชื่อ "*.cpp" | xargs -t rm -rf 2>&1

    RM -rf ./main.cpp ./version.cpp ./config.cpp ./data.cpp

    จะเห็นได้ว่ามีเพียงทีมเดียวที่อาสา RM และส่งรายชื่อไฟล์ไปให้ เพียงแต่ผลงานจะดูราวกับว่ามันถูกเรียกแยกกันสำหรับแต่ละไฟล์

    หากคุณใช้ตัวเลือก"-n1" แล้วภาพจะแตกต่างออกไป:

    $ ค้นหา -ชื่อ "*.cpp" | xargs-n 1 -t rm -rf 2>&1

    RM -rf ./main.cpp

    RM -rf ./version.cpp

    RM -rf ./config.cpp

    RM -rf ./data.cpp

    ที่นี่พฤติกรรมเป็นไปตามที่สัญญาไว้ทุกประการ จำตัวเลือกนี้ไว้และอย่าแปลกใจเลย xargs ทำงานผิดพลาดหากคุณไม่ใช้ตัวเลือกนี้ โปรดจำไว้ว่าในหลาย ๆ บทความบนอินเทอร์เน็ตคำสั่งด้วย xargs ไม่สามารถใช้งานได้ ผู้เขียนคิดว่าพวกเขารู้ว่าผลลัพธ์ควรเป็นอย่างไรและอย่าตรวจสอบสิ่งที่ "ชัดเจน" ด้วยซ้ำซึ่งเป็นผลมาจากการที่ผู้ใช้ที่ไม่ได้เตรียมตัวซึ่งตัดสินใจทำซ้ำสิ่งที่เขียนในบทความจะไม่เข้าใจอะไรเลยจริงๆ

    มีจุดที่ละเอียดอ่อนอีกจุดหนึ่ง xargs มีการจำกัดความยาวของสตรีมอินพุต และหากสตรีมอินพุตมีขนาดใหญ่เกินไป xargs จะแยกออกเป็นสองส่วนขึ้นไป และสำหรับแต่ละส่วนนั้นจะยังคงเรียกคำสั่งแยกกันซึ่งระบุไว้ทางด้านขวา เพื่อหลีกเลี่ยงสถานการณ์ที่ไม่คาดฝันดังกล่าว ให้ใช้ตัวเลือก"-n1" .

    คำสั่ง xargs โดยไม่มีข้อโต้แย้ง

    บางครั้งคุณอาจเจอสิ่งก่อสร้างที่น่าท้อใจ เช่น:

    tr -dc A-Za-z0-9_< /dev/urandom | head -c 10 | xargs

    คำสั่งนี้จะสร้าง รหัสผ่านแบบสุ่มความยาว 10 ตัวอักษร แต่คำสั่งหมายถึงอะไร? xargs ไม่มีข้อโต้แย้งที่ส่วนท้ายของคำสั่งนี้?

    คำตอบนั้นง่าย ทีม xargs โดยไม่มีข้อโต้แย้ง จริงๆ แล้วคิดว่าคำสั่งทางด้านขวาคือ/bin/เอคโค่ - และส่งต่อกระแสที่เข้ามาผ่านคำสั่งเสียงสะท้อน - เหตุใดจึงจำเป็น? ใน ในตัวอย่างนี้นี่เป็นเพียงเพื่อให้แน่ใจว่าผลลัพธ์สุดท้ายจะลงท้ายด้วยอักขระขึ้นบรรทัดใหม่ นี่คือตัวอย่างที่แสดงความแตกต่างระหว่างทีมที่ไม่มี xargs คือ xargs :

    > tr -dc A-Za-z0-9_< /dev/urandom | head -c 10

    7jk2qx4cX8>

    > tr -dc A-Za-z0-9_< /dev/urandom | head -c 10 | xargs

    zSlr2HsbSa

    ช่องว่างในชื่อไฟล์

    เนื่องจาก xargs ถือว่าช่องว่าง แท็บ และการขึ้นบรรทัดใหม่เป็นตัวคั่น จึงเกิดปัญหาในการประมวลผลชื่อไฟล์ที่มี อักขระช่องว่าง.

    โดยทั่วไป ชื่อไฟล์สำหรับอินพุตของโปรแกรม xargs จะได้รับมาจากผลลัพธ์ของคำสั่งหา - และเพื่อแก้ไขปัญหานี้ให้กับทีมงาน find มีตัวเลือก "-print0" - จะแทนที่ตัวแบ่งบรรทัดด้วยอักขระว่าง\x0 . และคำสั่ง xargs มีตัวเลือก "-0" (ลบศูนย์) ด้วยความช่วยเหลือของสตรีมอินพุตจะถูกแบ่งออกเป็นส่วนที่คั่นด้วยสัญลักษณ์\x0 .

    สมมติว่าไฟล์ปรากฏในไดเร็กทอรีที่มีชื่อ"ไฟล์ใหม่.cpp" - หากคุณไม่ได้ใช้ตัวเลือกการแปลงค่า Null เป็น Null สิ่งต่อไปนี้จะเกิดขึ้น:

    $ ค้นหา -ชื่อ "*.cpp" | xargs -n 1 -t rm -rf 2>&1

    rm -rf ./ใหม่

    ไฟล์ rm -rf.cpp

    และแน่นอนว่าไฟล์"ไฟล์ใหม่.cpp" จะไม่ถูกลบ หากคุณเพิ่มตัวเลือกข้างต้น คำสั่งจะทำงานได้อย่างถูกต้อง:

    $ ค้นหา -ชื่อ "*.cpp" -print0 | xargs -n 1 -t -0 rm -rf 2>&1

    RM -rf ./ไฟล์ใหม่.cpp

    และไฟล์จะถูกลบ

    จะเกิดอะไรขึ้นถ้าคุณไม่เขียนตัวเลือก "-n"?

    โปรดทราบว่าคำสั่งข้างต้นใช้ตัวเลือก"-n1" - จะเกิดอะไรขึ้นถ้าคุณไม่เขียนมัน? โดยหลักการแล้วทุกอย่างจะทำงานเหมือนกันทุกประการ แต่มีเพียงไม่กี่คนที่สามารถอธิบายวิธีการทำงานได้เนื่องจากคำสั่งที่มองเห็นจะเหมือนกัน แต่ผลลัพธ์จะแตกต่างออกไป นี่คือตัวอย่าง

    คำสั่งที่ไม่มีตัวเลือก "-n 1" และไม่มีตัวเลือกการแปลงค่า null:

    $ ค้นหา -ชื่อ "*.cpp" | xargs -t rm -rf 2>&1

    "เรม..." และจะไม่ลบไฟล์"ไฟล์ใหม่.cpp" .

    และตอนนี้คำสั่งที่ไม่มีตัวเลือก "-n 1" แต่มีตัวเลือกสำหรับการแปลงอักขระ null:

    $ ค้นหา -ชื่อ "*.cpp" -print0 | xargs -t -0 rm -rf 2>&1

    rm -rf ./main.cpp ./data.cpp ./config.cpp ./version.cpp ./new file.cpp

    จึงได้มีการสร้างทีมงานขึ้นมา"เรม..." ภายนอกเหมือนกับรุ่นก่อนหน้าอย่างแน่นอนแต่มันจะลบไฟล์ "new file.cpp" !

    เป็นการยากที่จะอธิบายว่ามันทำงานอย่างไร ท้ายที่สุดแล้วทางเลือก"-0" คือคำสั่ง xargs ไม่ใช่คำสั่ง rm - ในหน้าคำสั่งแมน RM ไม่มีข้อบ่งชี้ว่าหากชื่อไฟล์คั่นด้วยอักขระว่าง อักขระช่องว่างในชื่อไฟล์จะถือเป็นตัวอักษรแทนที่จะเป็นตัวคั่น สำหรับผู้เขียนบทความ พฤติกรรมนี้ยังคงเป็นปริศนา และจนถึงขณะนี้ยังไม่มีผู้เชี่ยวชาญคนไหนที่จะอธิบายสิ่งที่เกิดขึ้นจริงได้

    คำถามที่สำคัญที่สุด

    แต่คุณจะสร้างคำสั่งได้อย่างไรโดยที่คุณไม่ต้องเพิ่มลำดับอักขระที่พบทางด้านขวา? และถ้าคุณต้องการเพิ่มอย่างอื่นหลังจากค่าที่แทรกทางด้านขวาล่ะ? ฉันควรทำอย่างไร? แต่ไม่มีทาง! นี่คือคำตอบ ไม่สามารถสร้างคำสั่งที่กำหนดเองโดยใช้ xargs ได้ คุณสามารถสร้างคำสั่งที่ประกอบด้วยส่วนฐาน (คงที่) และส่วนขวา (ไวด์การ์ด) เท่านั้น นั่นคือทั้งหมด!

    หาก xargs อนุญาตให้คุณเพิ่มบางสิ่งหลังส่วนไวด์การ์ด การใช้คำสั่งนี้จะง่ายกว่ามาก ตัวอย่างเช่น เป็นไปได้ที่จะใส่เครื่องหมายคำพูดก่อนและหลังส่วนไวด์การ์ด และจะไม่มีปัญหากับการเว้นวรรคในชื่อไฟล์ แต่ไวยากรณ์ xargs ไม่อนุญาตให้มีพฤติกรรมดังกล่าว

    เป็นไปไม่ได้เลยที่จะสร้างใน *NIX คำสั่งที่ถูกต้อง- แน่นอนว่ามันเป็นไปได้ ในการดำเนินการนี้ คุณสามารถใช้คำสั่ง awk และฟังก์ชัน system() ได้ วิธีการทำเช่นนี้เขียนไว้ในบทความ: .