GNU ขนานและ xargs รันคำสั่งหลายชุดพร้อมกันกับอาร์กิวเมนต์ที่ต่างกัน ระวังเมื่อใช้ xargs ตอนนี้ค้นหาทั้งคำ

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 “FILE”
  2. คำสั่ง xargs ยอมรับคำสั่งจากอินพุตมาตรฐาน โดยคั่นด้วยช่องว่างหรือขึ้นบรรทัดใหม่ หากต้องการจัดกลุ่มคำสั่งเหล่านี้ คุณสามารถใช้ double หรือ คำพูดเดียว- คุณยังสามารถระบุตัวคั่นได้โดยใช้ตัวเลือก -d
  3. หากไม่มีการส่งอาร์กิวเมนต์ไปที่ xargs คำสั่ง /bin/echo จะถูกดำเนินการตามค่าเริ่มต้น
  4. ในหลายกรณี คำสั่ง xargs สามารถแทนที่ด้วย for loop ได้ เช่น คำสั่ง $find -พิมพ์ 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” เป็น “http://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éแล้ว - ดู (ที่ลิงค์เดียวกันคุณสามารถดูตัวอย่างคำสั่งที่น่าสนใจได้)

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

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

$ (sed "s/#.*//g"|sed "/^ *$/d"|tr "\n" ";"|xargs echo)< script.sh

บทสรุป

ดังที่เห็นได้จากการตรวจสอบ ความสามารถของ xargs นั้นกว้างกว่าที่เห็นในตอนแรกมาก เราหวังว่าตัวอย่างที่ให้ไว้ในบทความนี้จะเป็นประโยชน์กับคุณ หากคุณทราบถึงการใช้งาน 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 โดยปกติ ค้นหาคำสั่งส่งคืนรายการไฟล์ที่ตรงตามเกณฑ์บางประการ รายการนี้ถูกส่งไปยัง 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 เพื่อค้นหาเนื้อหา แยกไฟล์- นี่เป็นการเสียเวลาโดยไม่จำเป็นโดยสิ้นเชิง เนื่องจากเครื่องมืออย่าง 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 ประการที่สามารถช่วยคุณกำจัดข้อผิดพลาดที่พบบ่อยที่สุดได้ ทำความคุ้นเคยกับเทคนิคดีๆ เหล่านี้และพัฒนาทักษะบรรทัดคำสั่ง Unix ของคุณ