ฉันพยายามเรียกใช้หลายคำสั่งในสิ่งที่ฉันพบฉันจะทำสิ่งนี้ได้อย่างไร
find . -exec cmd1; cmd2
ดูเหมือนจะไม่ทำงาน มันรัน cmd2 แทนหลังจาก cmd1 ถูกเรียกใช้งานในทุกไฟล์
ฉันพยายามเรียกใช้หลายคำสั่งในสิ่งที่ฉันพบฉันจะทำสิ่งนี้ได้อย่างไร
find . -exec cmd1; cmd2
ดูเหมือนจะไม่ทำงาน มันรัน cmd2 แทนหลังจาก cmd1 ถูกเรียกใช้งานในทุกไฟล์
คำตอบ:
ในการสาธิตนี้ผมจะใช้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 expr2expr1 -o expr2
หรือ; expr2 ไม่ได้รับการประเมินถ้า expr1 เป็นจริง
หากคุณไม่สำคัญเกี่ยวกับ cmd1 ความสามารถในการป้องกัน cmd2 ไม่ให้ทำงานเนื่องจากรหัสข้อผิดพลาด0
:
find . -exec cmd1 \; -exec cmd2 \;
วิธีที่เชื่อถือได้เพียงวิธีเดียวในการทำให้ทั้งสองคำสั่งทำงานเสมอนี่คือfind
เรียกใช้เชลล์ที่จะรันคำสั่งตามลำดับ:
find . -exec bash -c 'cmd1; cmd2' filedumper {} \;
หากคุณไม่สนใจที่จะสร้างสคริปต์ที่ใช้ 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 ไม่สามารถเรียกใช้ฟังก์ชันเชลล์ที่คุณกำหนดไว้ในสคริปต์ของคุณ
ฉันได้ลองวิธีแก้ปัญหาก่อนหน้านี้ทั้งสองโดยไม่มีโชคมาก อันนี้ใช้ได้ดีสำหรับฉัน:
$ for i in `find . -exec echo {} \;`; do cmd1 $i; cmd2 $i; done
ลองคำสั่ง:
sudo find -name "*[!0-9][1-9].txt" -exec chmod 744 * {} \; -a -exec ls -l {} \; | sort | parallel ls -l
*
ใน-exec
ส่วนที่จะขยายไปยังไฟล์ทั้งหมดในไดเรกทอรีปัจจุบัน sudo
โดยเฉพาะอย่างยิ่งเมื่อใช้เป็น
-o
แล้ว