find -exec + vs find | xargs: อันไหนให้เลือก?


32

ผมเข้าใจว่า-execสามารถใช้ตัวเลือกในการเลียนแบบพฤติกรรมของ+ xargsมีสถานการณ์ใดบ้างที่คุณต้องการให้ฟอร์มหนึ่งเหนืออีกฟอร์มหนึ่ง?

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

คำตอบ:


21

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

ตัวอย่างเล็ก ๆ สองไฟล์ a.lst และ b.lst:

cat a.lst
fuddel.sh
fiddel.sh

cat b.lst
fuddel.sh

ไม่มีเคล็ดลับที่นี่ - ข้อเท็จจริงที่ว่าทั้งสองมี "fuddel" แต่มีเพียงหนึ่งเดียวเท่านั้นที่มี "fiddel"

สมมติว่าเราไม่รู้ เราค้นหาไฟล์ที่ตรงกับ 2 เงื่อนไข:

find -exec grep -q fuddel {} ";" -exec grep -q fiddel {} ";" -ls
192097    4 -rw-r--r--   1 stefan   stefan         20 Jun 27 17:05 ./a.lst

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

และหมายเหตุคุณสามารถติดตาม-execพร้อมคำสั่ง find อื่น ๆ เช่น-lsหรือ-deleteหรือสิ่งที่คล้ายกัน โปรดทราบว่าการลบไม่เพียง แต่ทำให้ rm (ลบไฟล์) แต่ยังลบ rmdir (ลบไดเรกทอรี) ด้วย

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

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

หากคุณเชื่อว่าคุณต้องการการหลอกลวงเพื่อค้นหา{} วงเล็บปีกกาอย่าลังเลที่จะเยี่ยมชมคำถามของฉันซึ่งขอหลักฐาน การยืนยันของฉันคือ: คุณทำไม่ได้


3
findโพสต์นี้ได้เปิดตาของฉันไปเป็นวิธีใหม่ของการใช้ ขอบคุณมาก!
rahmu

1
"ฉันไม่เห็นความได้เปรียบใด ๆ ในการใช้ -xargs" อะไรคือ-execวิธีการทำxargs -P4เพื่อให้สามสี่แกนไม่อยู่ไม่ได้ใช้งาน?
Damian Yerrick

1
@DamianYerrick: จบคำสั่ง -exec ที่ไม่ได้อยู่ใน ";" แต่มีเครื่องหมาย + (/ / เครื่องหมายบวก)
ไม่ทราบผู้ใช้

25

การไพพ์ชื่อไฟล์อย่างปลอดภัยเพื่อxargsให้คุณfindรองรับ-print0ตัวเลือกและคุณxargsมีตัวเลือกที่สอดคล้องกันเพื่ออ่าน ( --nullหรือ-0) มิฉะนั้นชื่อไฟล์ที่มีอักขระที่ไม่สามารถพิมพ์ได้หรือแบ็กสแลชหรือเครื่องหมายคำพูดหรือช่องว่างในชื่ออาจทำให้เกิดพฤติกรรมที่ไม่คาดคิด บนมืออื่น ๆ ที่find -exec {} +อยู่ในPOSIX findข้อมูลจำเพาะดังนั้นมันจึงเป็นแบบพกพาและมันเป็นเรื่องเกี่ยวกับเป็นที่ปลอดภัยและแน่นอนปลอดภัยกว่าfind -print0 | xargs -0 find | xargsผมอยากแนะนำให้ไม่เคยทำโดยไม่ต้องfind | xargs-print0


6
ข้อยกเว้นที่น่าสังเกตอย่างมากเกี่ยวกับการพกพาของfind … -exec … {} +OpenBSD ซึ่งเพิ่งได้รับคุณลักษณะนี้พร้อมกับเวอร์ชัน 5.1 ที่เปิดตัวในปี 2012 BSD ทั้งหมดมีมา-print0เป็นเวลาหลายปีแม้กระทั่ง OpenBSD Solaris บนมืออื่น ๆ ที่เกาะติด POSIX มีให้คุณได้รับและไม่มีการ-exec + -print0
Gilles 'ดังนั้น - หยุดความชั่วร้าย'

-print0เป็นความเจ็บปวดและถึงแม้ว่าคุณสามารถโต้เถียงxargs --delimiter "\n"ไม่เทียบเท่าฉันไม่เคยใช้อดีตหลังจากค้นพบหลัง
Sridhar Sarnobat

3
ฉันไม่เห็นว่า-0เจ็บปวดกว่า--delimiter "\n"อะไร
jw013

2
นอกจากนี้-0GNU ยังxargsต้อง-rหลีกเลี่ยงการเรียกใช้คำสั่งหากไม่มีอินพุต
Stéphane Chazelas

2
ปัญหาอีกอย่างหนึ่ง| xargs -r0 cmdก็คือว่าcmdstdin นั้นได้รับผลกระทบ (ขึ้นอยู่กับxargsการนำไปใช้มัน/dev/nullหรือไปป์
Stéphane Chazelas

10

หากคุณใช้-exec ... ;แบบฟอร์ม (การจำเพื่อหลบเครื่องหมายอัฒภาค) คุณกำลังเรียกใช้คำสั่งหนึ่งครั้งต่อหนึ่งชื่อไฟล์ หากคุณใช้-print0 | xargs -0คุณเรียกใช้หลายคำสั่งต่อชื่อไฟล์ แน่นอนคุณควรใช้-exec +แบบฟอร์มซึ่งทำให้หลายไฟล์ในบรรทัดคำสั่งเดียวและเร็วกว่ามากเมื่อมีไฟล์จำนวนมากเข้ามาเกี่ยวข้อง

บวกใหญ่ของการใช้ความสามารถในการเรียกใช้คำสั่งหลายขนานโดยใช้xargs xargs -Pสำหรับระบบมัลติคอร์ที่สามารถประหยัดเวลาได้มาก


6
คุณหมายแทน-P -pโปรดxargs -Pทราบว่าไม่ได้อยู่ในมาตรฐาน POSIX ในขณะfind -exec {} +ที่เป็นสิ่งสำคัญหากคุณจะพกพา
jw013

@Alexios คุณไม่จำเป็นต้องหลีกเลี่ยงเครื่องหมายบวกเพราะมันไม่มีความหมายพิเศษสำหรับเชลล์: ใช้find /tmp/ -exec ls "{}" +งานได้ดี
daniel kullmann

1
แน่นอนว่า Corrent ฉันได้หลบหนีทุกอย่างหลังจาก-execนั้นมาเป็นเวลานาน (ฉันเป็นนักทำโทษตนเองฉันไม่ได้ใช้เครื่องหมายคำพูดเพื่อหลบหนี{}ฉันพิมพ์เสมอ\{\}ไม่ต้องถาม) ทุกอย่างดูเหมือนว่ามันจะต้องหลบหนีในตอนนี้
Alexios

1
@Alexios: หากคุณพบตัวอย่าง (ยกเว้นการเป็นผู้ทำโทษตนเอง) ซึ่งการหลอกลวงผู้ช่วยจัดฟันมีประโยชน์โปรดระบุให้เป็นคำตอบสำหรับคำถามของฉันที่นี่ - afaik คำใบ้นี้ล้าสมัยและมีความเกี่ยวข้องกับ manpage เท่านั้น ฉันไม่เคยเห็นตัวอย่างที่find /tmp/ -exec ls {} +จะไม่ทำงาน
ผู้ใช้ที่ไม่รู้จัก

1
สำหรับฉันนี่คือความทรงจำของกล้ามเนื้อที่เกิดขึ้นในยุคของ SunOS 4 ตั้งแต่ฉันทำมันมาหลายปีฉันจึงไม่สังเกตเห็นเลยเลยเมื่อbashเริ่มยอมรับการจัดฟันคำต่อคำ ฉันค่อนข้างแน่ใจว่าอย่างน้อยหนึ่งในกระสุนเก่า ๆ ที่ฉันเคยใช้นั้นเหมาะสำหรับการจัดฟันหากไม่ได้หลบหนี
Alexios

8

เกี่ยวกับประสิทธิภาพฉันคิดว่า-exec … +มันจะดีกว่าเพราะมันเป็นเครื่องมือเดียวที่ทำงานได้ทั้งหมด แต่เป็นส่วนหนึ่งของเอกสารของ GNU findutilกล่าวว่า-exec … +อาจมีประสิทธิภาพน้อยกว่าในบางกรณี:

[พบกับ-exec … +]จะสามารถมีประสิทธิภาพน้อยกว่าการใช้ประโยชน์จากบางxargs; ตัวอย่างเช่นxargsอนุญาตให้สร้างบรรทัดคำสั่งใหม่ในขณะที่คำสั่งก่อนหน้านี้ยังคงดำเนินการอยู่และอนุญาตให้คุณระบุจำนวนคำสั่งเพื่อทำงานแบบขนาน อย่างไรก็ตามfind ... -exec ... +โครงสร้างมีข้อดีของการพกพาที่กว้าง GNU findutils ไม่สนับสนุน ' -exec ... +' จนกระทั่งรุ่น 4.2.12 [มกราคม 2005] ; หนึ่งในเหตุผลสำหรับเรื่องนี้คือมันมี '-print0กระทำ "" ในทุกกรณี

ฉันไม่แน่ใจว่าสิ่งที่ตั้งใจดังนั้นฉันถามในการแชทที่Derobertอธิบายว่าเป็น:

findอาจจะสามารถค้นหาไฟล์ชุดต่อไปในขณะที่-exec … +กำลังทำงานอยู่ แต่ก็ไม่ได้
find … | xargs …ทำเช่นนั้นเพราะการค้นหานั้นเป็นกระบวนการที่แตกต่างกันและมันจะทำงานต่อไปจนกว่าบัฟเฟอร์ของท่อจะเต็ม

(การจัดรูปแบบโดยฉัน)

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

ที่นี่ในเว็บไซต์นี้ฉันคิดว่าเป็นการดีกว่าที่จะแนะนำให้ผู้คนใช้-exec … +แบบฟอร์มทุกครั้งที่ทำได้เพราะเพียงเพราะมันง่ายกว่าและด้วยเหตุผลที่กล่าวไว้ในคำตอบอื่น ๆ ที่นี่ (เช่นการจัดการชื่อไฟล์แปลก ๆ โดยไม่ต้องคิดมาก)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.