Cách tiếp cận của @ meuh không hiệu quả vì -maxdepth 1
cách tiếp cận của anh ấy vẫn cho phép find
đọc nội dung của các thư mục ở cấp 1 để sau đó bỏ qua chúng. Nó cũng sẽ không hoạt động đúng với một số find
triển khai (bao gồm GNU find
) nếu một số tên thư mục chứa chuỗi byte không tạo thành các ký tự hợp lệ trong miền địa phương của người dùng (như đối với tên tệp trong mã hóa ký tự khác).
find . \( -name . -o -prune \) -extra-conditions-and-actions
là cách thức kinh điển hơn để triển khai GNU -maxdepth 1
(hoặc FreeBSD -depth -2
).
Nói chung, mặc dù, đó là điều -depth 1
bạn muốn ( -mindepth 1 -maxdepth 1
) vì bạn không muốn xem xét .
(độ sâu 0), và sau đó nó thậm chí còn đơn giản hơn:
find . ! -name . -prune -extra-conditions-and-actions
Vì -maxdepth 2
, điều đó trở thành:
find . \( ! -path './*/*' -o -prune \) -extra-conditions-and-actions
Và đó là nơi bạn chạy trong các vấn đề nhân vật không hợp lệ.
Chẳng hạn, nếu bạn có một thư mục được gọi Stéphane
nhưng é
được mã hóa trong bộ ký tự iso8859-1 (còn gọi là latin1) (0xe9 byte) như phổ biến nhất ở Tây Âu và Mỹ cho đến giữa những năm 2000, thì byte 0xe9 đó không phải là một ký tự hợp lệ trong UTF-8. Vì vậy, trong các ngôn ngữ UTF-8, *
ký tự đại diện (với một số find
triển khai) sẽ không khớp Stéphane
với *
0 hoặc nhiều ký tự và 0xe9 không phải là ký tự.
$ locale charmap
UTF-8
$ find . -maxdepth 2
.
./St?phane
./St?phane/Chazelas
./Stéphane
./Stéphane/Chazelas
./John
./John/Smith
$ find . \( ! -path './*/*' -o -prune \)
.
./St?phane
./St?phane/Chazelas
./St?phane/Chazelas/age
./St?phane/Chazelas/gender
./St?phane/Chazelas/address
./Stéphane
./Stéphane/Chazelas
./John
./John/Smith
My find
(khi đầu ra đi đến một thiết bị đầu cuối) hiển thị byte 0xe9 không hợp lệ như ?
trên. Bạn có thể thấy đó St<0xe9>phane/Chazelas
không phải là prune
d.
Bạn có thể làm việc xung quanh nó bằng cách làm:
LC_ALL=C find . \( ! -path './*/*' -o -prune \) -extra-conditions-and-actions
Nhưng lưu ý rằng điều đó ảnh hưởng đến tất cả các cài đặt ngôn ngữ find
và bất kỳ ứng dụng nào nó chạy (như thông qua các -exec
vị từ).
$ LC_ALL=C find . \( ! -path './*/*' -o -prune \)
.
./St?phane
./St?phane/Chazelas
./St??phane
./St??phane/Chazelas
./John
./John/Smith
Bây giờ, tôi thực sự nhận được một -maxdepth 2
lưu ý rằng é trong Stéphane thứ hai được mã hóa chính xác trong UTF-8 được hiển thị dưới ??
dạng các byte 0xc3 0xa9 (được coi là hai ký tự không xác định riêng lẻ trong ngôn ngữ C) của mã hóa UTF-8 không in các ký tự trong miền địa phương C.
Và nếu tôi đã thêm một -name '????????'
, tôi sẽ nhận được Stéphane sai (cái được mã hóa trong iso8859-1).
Để áp dụng cho các đường dẫn tùy ý thay vì .
, bạn sẽ làm:
find some/dir/. ! -name . -prune ...
cho -mindepth 1 -maxdepth 1
hoặc:
find some/dir/. \( ! -path '*/./*/*' -o -prune \) ...
cho -maxdepth 2
.
Tôi vẫn sẽ làm một:
(cd -P -- "$dir" && find . ...)
Đầu tiên bởi vì điều đó làm cho các đường dẫn ngắn hơn khiến nó ít có khả năng chạy vào đường dẫn quá dài hoặc liệt kê các vấn đề quá dài mà còn khắc phục được thực tế là find
không thể hỗ trợ các đối số đường dẫn tùy ý (ngoại trừ -f
với FreeBSD find
) vì nó sẽ bị nghẹt giá trị $dir
thích !
hoặc -print
...
Sự -o
kết hợp với phủ định là một mẹo phổ biến để chạy hai bộ -condition
/ -action
in độc lập find
.
Nếu bạn muốn chạy -action1
trên cuộc họp tệp -condition1
và độc lập -action2
với cuộc họp tệp -condition2
, bạn không thể thực hiện:
find . -condition1 -action1 -condition2 -action2
Như -action2
sẽ chỉ được chạy cho các tập tin đáp ứng cả hai điều kiện.
Cũng không:
find . -contition1 -action1 -o -condition2 -action2
Như -action2
sẽ không được chạy cho các tập tin đáp ứng cả hai điều kiện.
find . \( ! -condition1 -o -action1 \) -condition2 -action2
hoạt động như \( ! -condition1 -o -action1 \)
sẽ giải quyết đúng cho mọi tập tin. Giả định đó -action1
là một hành động (như -prune
, -exec ... {} +
) luôn trả về đúng . Đối với những hành động như -exec ... \;
có thể trả lại sai , bạn có thể muốn thêm một -o -something
nơi -something
là vô hại nhưng trả về đúng như -true
trong GNU find
hay -links +0
hay -name '*'
(mặc dù lưu ý các vấn đề về nhân vật không hợp lệ ở trên).
-depth -2
,-depth 1
... có thể được xem là tốt hơn so với GNU-maxdepth
/-mindepth