ค้นหา: -exec vs xargs (aka ทำไม "find | xargs basename" เบรค)


10

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

$ find . -name '*.deb' -print | xargs basename 
basename: extra operand `./pool/main/a/aalib/libaa1_1.4p5-37+b1_i386.deb'
Try `basename --help' for more information.

ฉันได้รับสิ่งเดียวกัน (ข้อผิดพลาดเดียวกันอย่างแน่นอน) กับรูปแบบอย่างใดอย่างหนึ่งเหล่านี้:

$ find . -name '*.deb' -print0 | xargs -0 basename 
$ find . -name '*.deb' -print | xargs basename {}

ในทางกลับกันการทำงานตามที่คาดไว้:

$ find . -name '*.deb' -exec basename {} \;
foo
bar
baz

สิ่งนี้เกิดขึ้นใน Cygwin ที่ทันสมัยและ Debian 5.0.3 การวินิจฉัยของฉันคือ xargs ด้วยเหตุผลบางอย่างผ่านสองบรรทัดอินพุตไปยังชื่อฐาน แต่ทำไม? เกิดอะไรขึ้นที่นี่?

คำตอบ:


23

เพราะbasenameต้องการเพียงพารามิเตอร์เดียว ... ไม่มาก และxargsสร้างพารามิเตอร์จำนวนมาก

วิธีแก้ปัญหาที่แท้จริงของคุณ (แสดงเฉพาะชื่อไฟล์):

 find . -name '*.deb' -printf "%f\n"

ซึ่งพิมพ์เพียง 'basename' (ค้นหาคน):

 %f     File's name with any leading directories
        removed (only the last element).

1
oooh .... / ตบหน้าผากอีกครั้ง / ฉันคิดว่าฉันต้องการหนังสือ "find for dummies" ...
quack quixote

ฉันคิดว่าประเด็นของxargsมันคือการสร้างรายการของข้อโต้แย้งและฟีดแต่ละคำสั่งที่มาหลังจาก? มิฉะนั้นแล้วความแตกต่างระหว่างนั้นfind . -name '*.deb' | basenameคืออะไร?
WindowsMaker

ขณะนี้ GNU basename มี-aตัวเลือก: "สนับสนุนอาร์กิวเมนต์หลายตัวและถือว่าแต่ละชื่อเป็น"
อธิการ

1
@WindowsMaker xargsแปลงstdinเป็นอาร์กิวเมนต์คำสั่ง ในทางตรงข้ามมันเป็นของที่แปลงข้อโต้แย้งในการecho stdoutความแตกต่างระหว่างfind ... | xargs -n1 basenameหรือfind ... | xargs basename -aและfind ... | basenameเป็นว่าอดีตสองจะทำงานร่วมกับการใช้งานที่ไม่สนใจbasename stdin
8bittree

19

ลองสิ่งนี้:

find . -name '*.deb' | xargs -n1 basename

นี่ไม่ใช่คำอธิบายนี่เป็นวิธีแก้ปัญหา และวิธีแก้ปัญหาก็ดีเหมือนกันเพียงแค่เรียก 'basename' ผ่าน -exec สำหรับไฟล์ใด ๆ ที่พบ
akira

4
+1 ... ในขณะที่ไม่มีคำอธิบายสิ่งนี้จะทำให้ฉันตรวจสอบสวิตช์ xargs ที่คุณแสดงซึ่งในที่สุดก็จะนำฉันไปสู่การเคลื่อนไหวของหน้าผาก - ตบที่ฉันเพิ่งใช้อ่านคำตอบของอากิระและจอห์นที ...
quack quixote

1
นี่คือวิธีที่ฉันทำ ฉันไม่รู้สึกอยากเรียนรู้รายละเอียดทั้งหมดของfindคำสั่งดังนั้นฉันใช้มันเพื่อค้นหาและแสดงรายการไฟล์เท่านั้นและฉันใช้ xargs เพื่อทุกอย่าง
ไรอันซี ธ อมป์สัน

4

basename ยอมรับการโต้แย้งเพียงครั้งเดียว การใช้-execงานได้อย่างถูกต้องเพราะแต่ละไฟล์{}จะถูกแทนที่ด้วยชื่อไฟล์ปัจจุบันที่กำลังประมวลผลและคำสั่งจะทำงานหนึ่งครั้งต่อหนึ่งไฟล์ที่ตรงกันแทนที่จะพยายามส่งอาร์กิวเมนต์ทั้งหมดไปยังชื่อไฟล์พื้นฐานในคราวเดียว


3

xargs สามารถถูกบังคับให้ส่งผ่านอาร์กิวเมนต์เดียวได้เช่นกัน ...

find . -name '*.deb' -print | xargs -n1 basename

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

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