bash find: รับไดเรกทอรีของไฟล์ที่พบ


12

ฉันมีโฟลเดอร์หลักชื่อ "parent_folder" ที่มีโฟลเดอร์ย่อยจำนวนมากในโฟลเดอร์ย่อยเหล่านี้เป็นไฟล์ชื่อ "foo.mp4"

ฉันสามารถค้นหาไฟล์เหล่านี้ได้อย่างง่ายดายโดยทำสิ่งนี้:

mymacbook:parent_folder username$ find ./ -name "foo.mp4" -exec echo {} \;

ตอนนี้จะส่งคืนพา ธ ของแต่ละไฟล์โดยสัมพันธ์กับ parent_folder /

./path/to/foo.mp4

ฉันจะกลับไปยังเส้นทางที่ไม่มีชื่อไฟล์ได้อย่างไร


1
man find ( ACTIONS ): -printf %h ไดเรกทอรีชั้นนำของชื่อไฟล์ (ทั้งหมดยกเว้นองค์ประกอบสุดท้าย) หากชื่อไฟล์ไม่มีเครื่องหมายสแลช (เนื่องจากอยู่ในไดเรกทอรีปัจจุบัน) ตัวระบุ% h จะขยายเป็น "." .
Costas

คุณสามารถแสดงตัวอย่างของสิ่งนั้นได้ไหม ฉันควรวางไว้ด้านหลัง '-exec' หรือก่อนหน้านี้หรือไม่
dubbelj

find ./ -name "foo.mp4" -printf "%h\n"จะพิมพ์พา ธ ไปยังไฟล์แต่ละไฟล์ที่พบ (หนึ่งต่อบรรทัด) มากกว่าปกติไม่มีใครใช้-exec echo {}ดังนั้นจึงมี-print(ค่าเริ่มต้นแม้ละเว้น) หรือprintfการกระทำ
Costas

2
@Costas -printfเป็น GNU เท่านั้น OP กล่าวถึง OS / X (ระบบ BSD)
Stéphane Chazelas

@ StéphaneChazelasขอบคุณ ฉันไม่ทราบข้อ จำกัด ดังกล่าวสำหรับ OS / X (BSD) ผู้ใช้ mac ที่น่าสงสาร!
Costas

คำตอบ:


20

ด้วยการGNUค้นหา:

 find . -name foo.mp4 -printf '%h\n'

กับfinds อื่น ๆชื่อไดเรกทอรีที่ระบุไม่มีอักขระขึ้นบรรทัดใหม่:

 find . -name foo.mp4 | sed 's|/[^/]*$||'

หรือ:

 find . -name foo.mp4 -exec dirname {} \;

แม้ว่าจะหมายถึงการรันหนึ่งdirnameคำสั่งต่อไฟล์

หากคุณต้องการเรียกใช้คำสั่งpathคุณสามารถทำได้ (ไวยากรณ์มาตรฐาน):

 find . -name "featured.mp4" -exec sh -c '
   for file do
     dir=${file%/*}
     ffmpeg -i "$file" -c:v libvpx -b:v 1M -c:a libvorbis "$dir" featured.webm
   done' sh {} +

แม้ว่าในกรณีนี้คุณอาจจะสามารถใช้-execdir(ส่วนขยาย BSD ยังมีอยู่ใน GNU find) ซึ่งchdir()ไปยังไดเรกทอรีของไฟล์:

 find . -name "featured.mp4" -execdir \
   ffmpeg -i {} -c:v libvpx -b:v 1M -c:a libvorbis . featured.webm \;

ระวังแม้ว่าว่าในขณะที่การดำเนินงานของกนูfindจะขยาย{}ไป./filenameที่นี่คน BSD filenameขยายตัวออกไป ตกลงที่นี่เนื่องจากชื่อไฟล์ถูกส่งผ่านเป็นอาร์กิวเมนต์ให้กับตัวเลือกและยังคงfeatured.mp4อยู่เสมอแต่สำหรับประเพณีอื่น ๆ คุณอาจต้องคำนึงถึงว่าชื่อไฟล์อาจขึ้นต้นด้วย-หรือ+(และเข้าใจว่าเป็นตัวเลือกโดยคำสั่ง) หรือมี=(และเข้าใจว่าเป็นการกำหนดตัวแปรโดย awk เป็นต้น) หรือตัวละครอื่น ๆ ที่ก่อให้เกิดปัญหาเช่นนี้perl -p/n (ไม่ใช่ทั้งหมดถูกแก้ไขโดยคำนำหน้าfindของGNU ./แต่ในกรณีนั้น) เป็นต้นซึ่งคุณอาจต้องคำนึงถึง .


เมื่อคุณสมัครfind .เป็น dirname คุณจะมี แทนเส้นทางทั้งหมด
PersianGulf

ตอนนี้ฉันจะแปลสิ่งนี้เป็นอย่างไร find ./ -name "featured.mp4" -exec ffmpeg -i "{}" -c:v libvpx -b:v 1M -c:a libvorbis [NEED DIRECTORY HERE] featured.webm \; ฉันใช้คำแนะนำที่สองที่คุณพูดถึง
dubbelj

@MohsenPahlevanzadeh ผู้ปฏิบัติการไม่ได้ขอเส้นทางที่แน่นอน แต่สำหรับชื่อของเส้นทาง
Stéphane Chazelas

@ StéphaneChazelasขออภัยที่ให้คะแนน
PersianGulf

ขอบคุณ @ StéphaneChazelas คุณช่วยฉันจัดคิว ffmpeg / ชุด
dubbelj

-1

คำสั่งด้านล่างนี้ยังสามารถใช้เพื่อดึงข้อมูลรายละเอียดไดเรกทอรี

find ./ -name "foo.mp4" | rev | cut -d"/" -f2- | rev

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