ฉันจะรันคำสั่งหลายคำสั่งเมื่อใช้การค้นหาได้อย่างไร


57

ฉันพยายามเรียกใช้หลายคำสั่งในสิ่งที่ฉันพบฉันจะทำสิ่งนี้ได้อย่างไร

find . -exec cmd1; cmd2

ดูเหมือนจะไม่ทำงาน มันรัน cmd2 แทนหลังจาก cmd1 ถูกเรียกใช้งานในทุกไฟล์

คำตอบ:


40

ในการสาธิตนี้ผมจะใช้sh -c 'echo first; false'(หรือtrue) -execเป็นครั้งแรก ที่จะให้ผลลัพธ์บางอย่างและยังมีผลรหัสทางออกที่เลือก จากนั้นecho secondจะถูกใช้สำหรับอันที่สอง สมมติว่ามีหนึ่งไฟล์ในไดเรกทอรีปัจจุบัน

$ find . -type f -exec sh -c 'echo first; false' \; -exec echo second \;
first
$ find . -type f -exec sh -c 'echo first; true' \; -exec echo second \;
first
second
$ find . -type f \( -exec sh -c 'echo first; false' \; -false -o -exec echo second \; \)
first
second
$ find . -type f \( -exec sh -c 'echo first; false' \; -false -o -exec echo second \; \)
first
second

คำสั่งจริงของประเภทนี้จะมีลักษณะดังนี้:

find . -type f \( -exec command1 \; -false -o -exec command2 \; \)

ในชุดที่สองวงเล็บที่อยู่ในกลุ่มจะมีสอง-execส่วน -falseระหว่างพวกเขาบังคับให้รัฐทดสอบเพื่อ "เท็จ" และ-oสาเหตุการแสดงออกถัดไป (ที่สอง-exec) -falseจะได้รับการประเมินเพราะ

จากman find:

expr1 expr2
สองนิพจน์ในแถวจะถูกนำไปร่วมกับนัย "และ"; expr2 ไม่ได้รับการประเมินถ้า expr1 เป็นเท็จ

expr1 -a expr2
เหมือนกับ expr1 expr2

expr1 -o expr2
หรือ; expr2 ไม่ได้รับการประเมินถ้า expr1 เป็นจริง


อ่าใช่ฉันลืมไป-oแล้ว
Ignacio Vazquez-Abrams

32

หากคุณไม่สำคัญเกี่ยวกับ cmd1 ความสามารถในการป้องกัน cmd2 ไม่ให้ทำงานเนื่องจากรหัสข้อผิดพลาด0:

find . -exec cmd1 \; -exec cmd2 \;

วิธีที่เชื่อถือได้เพียงวิธีเดียวในการทำให้ทั้งสองคำสั่งทำงานเสมอนี่คือfindเรียกใช้เชลล์ที่จะรันคำสั่งตามลำดับ:

find . -exec bash -c 'cmd1; cmd2' filedumper {} \;

2

หากคุณไม่สนใจที่จะสร้างสคริปต์ที่ใช้ cmd1 และ cmd2 นั่นก็เป็นเพียงแค่สิ่งนี้:

find . -exec myscript {} \;

หรือ

find . -exec myscript {} +

ใช้ \; หรือ + ขึ้นอยู่กับว่า myscript สามารถจัดการไฟล์ได้มากกว่าหนึ่งไฟล์ในแต่ละครั้ง (ดูลำบากหากมีช่องว่างในชื่อไฟล์ ฯลฯ )

จากประสบการณ์ของฉันการใส่สิ่งที่คุณทำในบทภาพยนตร์นั้นมีค่าเกือบตลอดเวลา หากคุณต้องทำครั้งเดียวคุณจะต้องทำอีกครั้ง

แต่เคล็ดลับที่เรียบร้อยก็คือการหาสิ่งที่อยู่ในสคริปต์:

if [ $# -gt 0 ]; then
    for each; do
        touch $each
    done
else
    find . -exec $0 {} +
fi

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


0

ฉันได้ลองวิธีแก้ปัญหาก่อนหน้านี้ทั้งสองโดยไม่มีโชคมาก อันนี้ใช้ได้ดีสำหรับฉัน:

$ for i in `find . -exec echo {} \;`; do cmd1 $i; cmd2 $i; done

สิ่งนี้จะไม่ทำงานหากรายการไฟล์ใหญ่เกินไป
อเล็กซ์

-3

ลองคำสั่ง:

sudo find -name "*[!0-9][1-9].txt" -exec chmod 744 * {} \; -a -exec ls -l {} \; | sort | parallel ls -l

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