bash find: lấy thư mục của tập tin tìm thấy


12

Tôi có một thư mục mẹ có tên "Parent_folder" với rất nhiều thư mục con, trong các thư mục con này là một tệp có tên "foo.mp4".

Tôi có thể tìm thấy các tệp này một cách dễ dàng bằng cách làm điều này:

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

Bây giờ trả về đường dẫn của mỗi tệp, liên quan đến Parent_folder /

./path/to/foo.mp4

Làm thế nào tôi có thể trở lại chỉ đường dẫn, mà không có tên tệp?


1
man find ( HÀNH ĐỘNG ): Thư mục -printf %h hàng đầu của tên tệp (tất cả trừ phần tử cuối cùng). Nếu tên tệp không chứa dấu gạch chéo (vì nó nằm trong thư mục hiện tại) thì trình xác định% h mở rộng thành "." .
Costas

Bạn có thể cho thấy một ví dụ về điều đó? Tôi nên đặt nó phía sau '-exec' hay trước đó?
dubbelj

find ./ -name "foo.mp4" -printf "%h\n"sẽ in đường dẫn đến từng tệp được tìm thấy (từng dòng một). Nhiều hơn bình thường không ai sử dụng -exec echo {}do đó có -print(mặc định thậm chí bỏ qua) hoặc printfhành động.
Costas

2
@Costas, -printfchỉ dành cho GNU. OP đề cập đến OS / X (hệ thống BSD).
Stéphane Chazelas

@ StéphaneChazelas Cảm ơn. Tôi không biết giới hạn như vậy đối với OS / X (BSD). Người dùng nghèo 'mac!
Costas

Câu trả lời:


20

Với GNUtìm:

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

Với các tên khác find, tên thư mục được cung cấp không chứa các ký tự dòng mới:

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

Hoặc là:

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

mặc dù điều đó có nghĩa là chạy một dirnamelệnh cho mỗi tệp.

Nếu bạn cần chạy một lệnh trên đó path, bạn có thể làm (cú pháp chuẩn):

 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 {} +

Mặc dù trong trường hợp này, bạn có thể sử dụng -execdir(một phần mở rộng BSD cũng có sẵn trong GNU find), chdir()thuộc thư mục của tệp:

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

Coi chừng rằng trong khi triển khai GNU findsẽ mở rộng {}tới ./filenameđây, các BSD sẽ mở rộng sang filename. Ở đây vẫn ổn vì tên tệp được chuyển làm đối số cho một tùy chọn và luôn luôn là vậy featured.mp4, nhưng đối với các cách sử dụng khác, bạn có thể phải tính đến việc tên tệp có thể bắt đầu bằng -hoặc +(và được hiểu là một tùy chọn của lệnh) hoặc chứa =(và được hiểu như là một nhiệm vụ biến bằng cách awk chẳng hạn), hoặc các ký tự khác gây loại vấn đề vớiperl -p/n (không phải tất cả trong số họ cố định bởi GNU find's ./tiền tố mặc dù trong trường hợp đó), vv, mà bạn có thể phải đưa vào tài khoản .


Khi bạn áp dụng find ., như dirname bạn sẽ có. thay vì toàn bộ con đường.
Tiếng Ba Tư

Bây giờ tôi sẽ dịch nó như thế nào? find ./ -name "featured.mp4" -exec ffmpeg -i "{}" -c:v libvpx -b:v 1M -c:a libvorbis [NEED DIRECTORY HERE] featured.webm \; Tôi đang sử dụng đề xuất thứ hai mà bạn đề cập.
dubbelj

@MohsenPahlevanzadeh, OP không yêu cầu một đường dẫn tuyệt đối, nhưng đối với tên hiệu của đường dẫn.
Stéphane Chazelas

@ StéphaneChazelas Xin lỗi vì đã bỏ phiếu.
Tiếng Ba Tư

Cảm ơn @ StéphaneChazelas. Bạn đã giúp tôi thực hiện một hàng đợi / đợt ffmpeg
dubbelj

-1

Lệnh bên dưới cũng có thể được sử dụng để lấy chỉ các chi tiết thư mục.

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

Có vẻ hơi quá khi gọi ba tiện ích bên ngoài chỉ để cắt một chuỗi.
Kusalananda
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.