“ {} \;” หมายความว่าอะไรในคำสั่ง Linux


37

บางครั้งฉันเห็นคำสั่งต่อไปนี้:

find . -name  * -exec ls -a {} \;

ฉันถูกขอให้ดำเนินการนี้

ที่{} \;นี่หมายความว่าอย่างไร


1
-name *ซ้ำซ้อน
เควิน

3
ตรวจสอบคำอธิบายของเชลล์สำหรับคำถามประเภทอื่นเช่นนี้ นี่คือผลลัพธ์สำหรับคำสั่งของคุณ .
Glutanimate

8
-name *เลวร้ายยิ่งกว่าซ้ำซ้อน เนื่องจาก*unquote เชลล์จะขยายไปยังรายการชื่อไฟล์ในโฟลเดอร์ปัจจุบันโดยมีการเว้นวรรคที่ไม่ถูกต้องนำไปสู่ผลลัพธ์ที่ไม่คาดคิดหรือข้อความแสดงข้อผิดพลาด ในฐานะที่เป็นจุดพิเศษfindมีฟังก์ชั่นมากมายโดยหนึ่งในนั้นคือรายการไฟล์ -execหลีกเลี่ยงการนี้ต้องใช้ เช่นคุณสามารถใช้หรือfind . -print find . -lsสุดท้ายมีสองวิธีที่จะหลบหนีกึ่งลำไส้ใหญ่: ทั้งที่คุณทำกับเครื่องหมาย, หรือโดยการอ้าง:\; ';'ใช้สิ่งที่คุณรู้สึกสะดวกสบายมากขึ้นด้วย
Paddy Landau

คำตอบ:


48

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

อัฒภาคลงท้ายคำสั่งดำเนินการโดย; execจะต้องมีการหนีไปกับ\เพื่อให้เปลือกที่คุณใช้findภายในไม่รักษามันเป็นตัวละครพิเศษของตัวเอง findแต่ส่งผ่านไปยัง

ดูบทความนี้สำหรับรายละเอียดเพิ่มเติม


นอกจากนี้ยังfindจัดเตรียมการปรับให้เหมาะสมด้วยexec cmd {} +- เมื่อเรียกใช้เช่นนั้นfindผนวกไฟล์ที่พบท้ายคำสั่งแทนที่จะเรียกใช้หนึ่งครั้งต่อไฟล์ (เพื่อให้คำสั่งรันเพียงครั้งเดียวหากเป็นไปได้)

ความแตกต่างในพฤติกรรม (ถ้าไม่ได้อยู่ในประสิทธิภาพ) จะสังเกตได้ง่ายถ้าวิ่งด้วยlsเช่น

find ~ -iname '*.jpg' -exec ls {} \;
# vs
find ~ -iname '*.jpg' -exec ls {} +

สมมติว่าคุณมีjpgไฟล์บางไฟล์ (ที่มีพา ธสั้นพอ ) ผลลัพธ์คือหนึ่งบรรทัดต่อไฟล์ในกรณีแรกและlsพฤติกรรมมาตรฐานของการแสดงไฟล์ในคอลัมน์สำหรับหลัง


1
ฉันคิดว่ามันจะเป็นประโยชน์สำหรับคุณเพื่อความคมชัดด้วย\; +
เควิน

มันแตกต่างจากfind . -name * | ls -a -อย่างไร
András Hummer

@DrH จุดคือไม่ให้เปลือกทำสัญลักษณ์แทนการขยายตัว findแต่ผ่านการแสดงออกสัญลักษณ์แทนเพื่อ นอกจากนี้การส่งออกของlsในกรณีนี้เห็นได้ชัดว่าไม่ได้ขึ้นอยู่กับการป้อนข้อมูล - ไม่ว่าสิ่งที่ฉันใช้เป็นตัวกรองสำหรับfind, lsเพียงแสดงเนื้อหาไดเรกทอรีการทำงานและนั่นคือทั้งหมด ตรวจสอบตัวอย่างVSfind ~ -iname '*.jpg' -exec ls -a {} \; find ~ -iname '*.jpg' | ls -a
moon.musick

@DrH echo 'foo' | ls -aหรือแม้กระทั่ง
moon.musick

@ moon.musick ฉันเชื่อว่าคุณพลาดความสำคัญ-ในls -a -คำสั่งของคุณเมื่อทดสอบสิ่งที่ @ dr-h สอบถาม
Daniel Llewellyn

20

จากmanpage สำหรับfindคำสั่งไอคอน Manpage :

-exec command ;
              Execute  command;  true if 0 status is returned.  All following arguments to find are taken to be arguments to
              the command until an argument consisting of `;' is encountered.  The string `{}' is replaced  by  the  current
              file name being processed everywhere it occurs in the arguments to the command, not just in arguments where it
              is alone, as in some versions of find.  Both of these constructions might need to be escaped (with a  `\')  or
              quoted  to  protect them from expansion by the shell.

ดังนั้นนี่คือคำอธิบาย:

{}หมายถึง "ผลลัพธ์ของfind" เช่นเดียวกับใน "สิ่งที่findพบ" findคืนค่าพา ธ ของไฟล์ที่คุณต้องการใช่ไหม ดังนั้น{}แทนที่มัน มันเป็นตัวยึดสำหรับแต่ละไฟล์ที่findคำสั่งตั้งอยู่ (นำมาจากที่นี่ )

\;ส่วนหนึ่งเป็นพื้นบอกfind"โอเคฉันทำกับคำสั่งที่ฉันต้องการที่จะดำเนินการ"

ตัวอย่าง:

สมมติว่าฉันอยู่ในไดเรกทอรีที่เต็มไปด้วย.txtไฟล์ จากนั้นฉันก็วิ่ง:

find . -name  '*.txt' -exec cat {} \;

ส่วนแรกfind . -name *.txtส่งคืนรายการ.txtไฟล์ ส่วนที่สอง-exec cat {} \;จะดำเนินการตามcatคำสั่งสำหรับทุกไฟล์พบโดยfindดังนั้นcat file1.txt, cat file2.txtและอื่น ๆ


4
ส่วนที่จะต้องถูกยกมาเป็น*.txt '*.txt'นี่เป็นเพราะหากมี.txtไฟล์ในโฟลเดอร์ปัจจุบันเชลล์จะขยายไฟล์นี้และคุณจะได้รับผลลัพธ์ที่ไม่ถูกต้องหรือข้อความแสดงข้อผิดพลาด find -name '*.txt' -exec cat {} \;
Paddy Landau

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