คำตอบของ muruนั้นเหมาะสมและเหมาะสมกับกรณีที่เราต้องการพิมพ์บางอย่างหากพบไฟล์ สำหรับกรณีทั่วไปเมื่อเราต้องการรันคำสั่งภายนอกเช่นecho
เราสามารถใช้การ-exec
ตั้งค่าสถานะ
$ find . -name 'xac' -exec echo "I found " {} \; -quit
I found ./xac
{}
ส่วนหนึ่งผ่านชื่อไฟล์คำสั่งระหว่าง-exec
และ\;
เป็นข้อโต้แย้ง หมายเหตุ\
ก่อน;
- ป้องกันไม่ให้มันจากเปลือกตีความมันในการปิดเปลือกหมายอัฒภาคปลายคำสั่ง แต่เมื่อหนีออกมาด้วยการเฉือนเปลือกจะรักษามันเป็นข้อความ literall จะถูกส่งผ่านไปยังfind
คำสั่งและคำสั่งที่จะหามันทำหน้าที่เป็นปิด-exec
การขัดแย้งธง
สำหรับการสร้าง conditionals ของif found do this; else do that
sort เราสามารถใช้ประโยชน์จาก substition คำสั่ง$()
และtest
command (aka [
):
$ [ "x$(find . -name 'noexist' -print -quit)" != "x" ] && echo "found" || echo "not found"
not found
$ [ "x$(find . -name 'xac' -print -quit)" != "x" ] && echo "found" || echo "not found"
found
พูดถึงความคิดเห็นของแดน
แดนในความคิดเห็นที่ถาม:
จะไม่สะท้อน "ฉันพบ {}" ดีกว่าเสียงสะท้อน "ฉันพบ" {} หรือไม่ อาจเป็นเพราะเสียงสะท้อนได้ดี แต่ถ้ามีคนคัดลอกคำสั่งและแทนที่เสียงสะท้อนด้วยคำสั่งอื่นพวกเขาอาจมีปัญหา
มาทำความเข้าใจปัญหาก่อนกัน โดยปกติแล้วใน shells จะมีแนวคิดเกี่ยวกับการแบ่งคำซึ่งหมายถึงตัวแปรที่ไม่ได้กล่าวถึงและพารามิเตอร์ตำแหน่งจะถูกขยายและถือเป็นรายการแยกต่างหาก ตัวอย่างเช่นถ้าคุณมีตัวแปรvar
และจะมีhello world
ข้อความเมื่อคุณทำtouch $var
เชลล์จะทำลายมันลงเป็นสองรายการแยกต่างหากhello
และworld
และtouch
จะเข้าใจว่าราวกับว่าคุณกำลังพยายามที่จะสร้าง 2 ไฟล์แยกเป็นสัดส่วน ถ้าคุณทำtouch "$var"
แล้วเปลือกจะถือว่าhello world
เป็นหนึ่งหน่วยและtouch
จะสร้างหนึ่งไฟล์เท่านั้น สิ่งสำคัญคือต้องเข้าใจว่าสิ่งนี้เกิดขึ้นเพียงเพราะเปลือกทำงานอย่างไร
ในทางตรงกันข้ามfind
จะไม่ประสบกับพฤติกรรมดังกล่าวเนื่องจากคำสั่งถูกประมวลผลด้วยfind
ตัวเองและดำเนินการโดยการexecvp()
เรียกของระบบดังนั้นจึงไม่มีเชลล์ที่เกี่ยวข้อง ในขณะที่เครื่องหมายปีกกามีความหมายพิเศษในกระสุนเพราะมันปรากฏอยู่ตรงกลางของfind
คำสั่งและไม่ใช่จุดเริ่มต้นพวกเขาไม่มีความหมายพิเศษกับกระสุนในกรณีนี้ นี่คือตัวอย่าง ลองสร้างชื่อไฟล์ที่ยากขึ้นมาหน่อยและลองส่งมันเป็นอาร์กิวเมนต์เพื่อstat
สั่ง
$ touch with$'\t'tab.txt with$' 'space.txt with$'\n'newline.txt
$ find -type f -exec stat -c "%F" {} \; -print
regular empty file
./with?newline.txt
regular empty file
./with space.txt
regular empty file
./with?tab.txt
ดังที่คุณเห็นstat
ได้รับชื่อไฟล์ยากfind
ๆ ซึ่งเป็นหนึ่งในเหตุผลหลักที่แนะนำให้ใช้ในสคริปต์แบบพกพาและมีประโยชน์อย่างยิ่งเมื่อคุณสำรวจทรีไดเรกทอรีและต้องการทำบางสิ่งบางอย่างกับชื่อไฟล์ที่อาจมี ตัวอักษรพิเศษในพวกเขา find
ดังนั้นจึงไม่จำเป็นที่จะพูดวงเล็บปีกกาสำหรับคำสั่งดำเนินการใน
มันเป็นเรื่องที่แตกต่างเมื่อกระสุนเข้ามาเกี่ยวข้อง บางครั้งคุณต้องใช้เชลล์เพื่อประมวลผลชื่อไฟล์ ในกรณีนั้นการอ้างอิงจะมีความสำคัญ แต่สิ่งสำคัญคือต้องตระหนักว่าไม่ใช่ปัญหาของการค้นหา - เป็นเชลล์ที่แยกคำออก
$ find -type f -exec bash -c "stat {}" sh \;
stat: cannot stat './with': No such file or directory
sh: line 1: newline.txt: command not found
stat: cannot stat './with': No such file or directory
stat: cannot stat 'space.txt': No such file or directory
stat: cannot stat './with': No such file or directory
stat: cannot stat 'tab.txt': No such file or directory
ดังนั้นเมื่อเราเสนอราคาภายในเชลล์มันจะทำงานได้ find
แต่อีกครั้งว่าเป็นสิ่งสำคัญสำหรับเปลือกไม่
$ find -type f -exec bash -c "stat -c '%F' '{}'" sh \;
regular empty file
regular empty file
regular empty file
/some/path
บอกให้ค้นหาว่าจะเริ่มมองที่ใด แต่ไม่มีอะไรบอกได้ว่าจะมองหาอะไร เหมือนกันในคำตอบที่เชื่อมโยงของคุณfind /some/path -name xac -print0 -quit | grep -qz . && echo found
สิ่งที่ไม่ทำงานสำหรับฉันก็คือ ฉันพลาดอะไรไปหรือเปล่า?