ฉันต้องการใช้คำสั่ง find เพื่อค้นหาไฟล์ทั้งหมดที่มีนามสกุล (avi) ที่ซึ่งชื่อไฟล์เดียวกันกับนามสกุลอื่น (mp4) ไม่มีอยู่จริง
ดังนั้นเมื่อพิจารณาไฟล์เหล่านี้:
a.avi
a.mp4
c.avi
มันควรจะส่งผลให้พบไฟล์ c.avi เท่านั้น
ฉันต้องการใช้คำสั่ง find เพื่อค้นหาไฟล์ทั้งหมดที่มีนามสกุล (avi) ที่ซึ่งชื่อไฟล์เดียวกันกับนามสกุลอื่น (mp4) ไม่มีอยู่จริง
ดังนั้นเมื่อพิจารณาไฟล์เหล่านี้:
a.avi
a.mp4
c.avi
มันควรจะส่งผลให้พบไฟล์ c.avi เท่านั้น
คำตอบ:
สิ่งนี้จะทำอย่างไร
find . -name '*.avi' -type f -execdir bash -c 'f=("${0%avi}"*);((${#f[@]}==1))' {} \; -print
ฉันจะพยายามอธิบายวิธีการทำงาน
จริงๆแล้วมันง่ายมาก: ค้นหาไฟล์ทั้งหมดในไดเรกทอรีปัจจุบันเพื่อให้ชื่อนั้นมีavi
นามสกุล สำหรับแต่ละไฟล์สมมติว่าไฟล์นั้นX.avi
ทำงานในไดเรกทอรีที่มีอยู่ใน ( execdir
) คำสั่ง:
bash -c 'f=("${0%avi}"*);((${#f[@]}==1))' {}
ที่จะถูกแทนที่ด้วยชื่อไฟล์ในกรณีที่การทดสอบของเรา{}
X.avi
ดังนั้นนี่คือ
bash -c 'f=("${0%avi}"*);((${#f[@]}==1))' X.avi
ณ จุดนี้ให้ฉันเน้นว่าสิ่งนี้ปลอดภัย 100% เกี่ยวกับช่องว่างและสัญลักษณ์ตลกอื่น ๆ ในชื่อไฟล์! ตอนนี้คุณเห็นข้อมูลโค้ดที่ bash จะทำงานหรือไม่ ฉันหมายถึงตัวอย่างนี้
f=("${0%avi}"*);((${#f[@]}==1))
มันจะถูกเรียกใช้งานโดยมีพารามิเตอร์ตำแหน่ง 0-th ตั้งเป็นชื่อไฟล์ของเรา X.avi
ในตัวอย่างการทดสอบของเรามันเป็น
ส่วน"${0%avi}"
ขยายไปยังชื่อไฟล์โดยavi
ลบส่วนท้าย(btw ชื่อไฟล์นี้รับประกันว่าจะมีนามสกุลนี้ ณ จุดนี้) และส่วน"${0%avi}"*
จะขยายไปยังไฟล์ทั้งหมดในไดเรกทอรีปัจจุบัน (จำไว้ส่วนที่มีไฟล์) ที่มี.avi
ส่วนขยาย. ในตัวอย่างทดสอบของเรานี่เป็นเช่น:
X.*
จากนั้นเราสร้างอาร์เรย์f
จากสิ่งเหล่านี้และในที่สุดเราออกจากbash
กระบวนการนี้ด้วยความสำเร็จหากf
มีเพียงองค์ประกอบเดียว (ดังนั้นมีแนวโน้มมากมีf
เพียงX.avi
ในตัวอย่างทดสอบของเรา) และความล้มเหลวเป็นอย่างอื่น หากนี่เป็นความสำเร็จเราจะพิมพ์ชื่อไฟล์
:D
วิธีการแก้ปัญหาด้วย 2 exec () s:
หา -name '* .avi' -print | \ perl -n -e '$ x = $ _; $ x = ~ s / \. avi \ s * $ /. mp4 /; (-e $ x) || พิมพ์'
ขั้นตอน:
ตัวเลือกอื่น: ค้นหาทั้งหมด.mp4
และ.avi
ไฟล์จากนั้นลบไฟล์ที่มีนามสกุลทั้งสองจากรายการและกำจัดไฟล์. mp4 ที่เหลืออยู่:
find . -name '*.avi' -or -name '*.mp4' |
rev | sort -t. -k2 -k1,1 | uniq -s3 -u | grep -v '^4pm' | rev | sort
(สมมติว่าไม่มีไฟล์ใดขึ้นบรรทัดใหม่ในชื่อ)
วิธีแก้ปัญหาด้วย 3 exec () s:
find . -name '*.avi' -print | \
sed 's/\(.*\)\.avi$/if [ ! -f "\1.mp4" ]; then echo "\1.avi"; fi/' | \
sh
ขั้นตอน:
touch '" ]; then rm -rf /; [ ! -f ".avi'
ฉันหวังว่าฉันจะทำได้ :D
แปลกใจ