find
(đối với các vị từ -name
/ -path
tiêu chuẩn) sử dụng các mẫu ký tự đại diện giống như các khối (lưu ý rằng đó {a,b}
không phải là toán tử toàn cục; sau khi mở rộng, bạn nhận được hai khối). Sự khác biệt chính là việc xử lý các dấu gạch chéo (và các tệp dấu chấm và thư mục không được xử lý đặc biệt trong find
). *
trong ảm đạm sẽ không mở rộng một số thư mục. */*/*
sẽ gây ra tới 2 cấp độ của các thư mục được liệt kê. Việc thêm -path './*/*/*'
sẽ khớp với bất kỳ tệp nào sâu ít nhất 3 cấp và sẽ không dừng find
việc liệt kê nội dung của bất kỳ thư mục nào ở bất kỳ độ sâu nào.
Đối với đặc biệt đó
./foo*bar/quux[A-Z]{.bak,}/pic[0-9][0-9][0-9][0-9]?.jpg
đôi chút, thật dễ dịch, bạn muốn thư mục ở độ sâu 3, vì vậy bạn có thể sử dụng:
find . -mindepth 3 -maxdepth 3 \
\( -path './foo*bar/quux[A-Z].bak/pic[0-9][0-9][0-9][0-9]?.jpg' -o \
-path './foo*bar/quux[A-Z]/pic[0-9][0-9][0-9][0-9]?.jpg' \) \
-exec cmd {} +
(hoặc -depth 3
với một số find
triển khai). Hoặc POSIXly:
find . -path './*/*/*' -prune \
\( -path './foo*bar/quux[A-Z].bak/pic[0-9][0-9][0-9][0-9]?.jpg' -o \
-path './foo*bar/quux[A-Z]/pic[0-9][0-9][0-9][0-9]?.jpg' \) \
-exec cmd {} +
Mà sẽ đảm bảo rằng những người *
và ?
không thể phù hợp với /
nhân vật.
( find
, trái với các thông tin sẽ đọc nội dung của các thư mục khác với các thư mục trong thư foo*bar
mục hiện tại¹ và không sắp xếp danh sách các tệp. Nhưng nếu chúng ta bỏ qua vấn đề phù hợp với [A-Z]
hoặc hành vi của *
/ ?
liên quan đến các ký tự không hợp lệ là không xác định, bạn sẽ nhận được cùng một danh sách các tệp).
Nhưng trong mọi trường hợp, như @muru đã chỉ ra , không cần phải dùng đến find
nếu chỉ để chia danh sách các tệp thành nhiều lần chạy để vượt qua giới hạn của lệnh execve()
gọi hệ thống. Một số shell như zsh
(với zargs
) hoặc ksh93
(với command -x
) thậm chí có hỗ trợ dựng sẵn cho điều đó.
Ví dụ, với zsh
(các quả cầu cũng có tương đương -type f
và hầu hết các find
vị từ khác ), ví dụ:
autoload zargs # if not already in ~/.zshrc
zargs ./foo*bar/quux[A-Z](|.bak)/pic[0-9][0-9][0-9][0-9]?.jpg(.) -- cmd
( (|.bak)
Là một trái điều hành glob tới {,.bak}
, các (.)
glob vòng loại là tương đương với find
's -type f
, thêm oN
vào đó để bỏ qua sắp xếp giống như với find
, D
bao gồm dot-file (không áp dụng cho glob này))
Để find
thu thập dữ liệu cây thư mục như các quả cầu, bạn sẽ cần một cái gì đó như:
find . ! -name . \( \
\( -path './*/*' -o -name 'foo*bar' -o -prune \) \
-path './*/*/*' -prune -name 'pic[0-9][0-9][0-9][0-9]?.jpg' -exec cmd {} + -o \
\( ! -path './*/*' -o -name 'quux[A-Z]' -o -name 'quux[A-Z].bak' -o -prune \) \)
Đó là prune tất cả các thư mục ở cấp 1, ngoại trừ foo*bar
những người thân, và tất cả ở cấp 2 trừ quux[A-Z]
hoặc quux[A-Z].bak
những người thân, và sau đó chọn pic...
những người ở mức 3 (và prune tất cả các thư mục ở cấp đó).
-path
hoặc-ipath
.find . -path './foo*bar/quux[A-Z]/pic[0-9][0-9][0-9][0-9]?.jpg'
nên làm việc - ngoại trừ rằng nó sẽ phù hợp/fooz/blah/bar/quuxA/pic1234d.jpg
. Đó sẽ là một vấn đề?