Lệnh find: các tùy chọn '-mindepth' xung đột với hành động '-prune'


8

Nếu cấu trúc tệp như thế này:

/a/p/c/d...
/c/a/c/g/f/...
/a/c/d/e/...
...

Và tôi muốn làm điều này:

find -mindepth 3 -type d -name p -prune -or -name c -print

Tuy nhiên, lệnh này sẽ không cắt thư mục 'p' và dòng đầu tiên sẽ được bao gồm. Tôi biết đó thực sự không phải là một cuộc xung đột. Nhưng làm thế nào để cắt tỉa 'p' với tâm trí được áp dụng?


Tôi lấy nó delà tập tin, không phải thư mục?
Anthon

Câu trả lời:


1

Tôi nghĩ rằng tôi sẽ làm theo cách này:

find -mindepth 3 -type d ! -path '*/p/*' -name c -print

Dựa trên phản hồi của @StephaneChazelas, tôi tin rằng phương pháp này sẽ loại bỏ việc tìm kiếm bên ngoài vào bất kỳ /p/thư mục nào :

find -mindepth 3 -type d -path '*/p/*' -prune -o -name c -print

Phân tích một tìm

Để so sánh các lệnh find, bạn có thể thêm công tắc gỡ lỗi -D searchđể bạn có thể thấy cách tìm kiếm cụ thể sẽ thực hiện so với lệnh khác.

Tôi đã chạy lệnh của @StephaneChazelas so với của tôi để xem sự khác biệt ở đâu. Hai lệnh được chạy và đầu ra của chúng được chạy vào sdiffbên dưới:

$ sdiff \
<(find -D search -mindepth 3 -type d -path '*/p/*' -prune -o -name c -print 2>&1) \
<(find -D search -type d -name p -prune -o -path './*/*/*' -name c -print 2>&1)
consider_visiting (early): `.': fts_info=FTS_D , fts_level= 0   consider_visiting (early): `.': fts_info=FTS_D , fts_level= 0
consider_visiting (late): `.': fts_info=FTS_D , isdir=1 ignor | consider_visiting (late): `.': fts_info=FTS_D , isdir=1 ignor
consider_visiting (early): `./a': fts_info=FTS_D , fts_level=   consider_visiting (early): `./a': fts_info=FTS_D , fts_level=
consider_visiting (late): `./a': fts_info=FTS_D , isdir=1 ign | consider_visiting (late): `./a': fts_info=FTS_D , isdir=1 ign
consider_visiting (early): `./a/c': fts_info=FTS_D , fts_leve   consider_visiting (early): `./a/c': fts_info=FTS_D , fts_leve
consider_visiting (late): `./a/c': fts_info=FTS_D , isdir=1 i | consider_visiting (late): `./a/c': fts_info=FTS_D , isdir=1 i
consider_visiting (early): `./a/c/d': fts_info=FTS_D , fts_le   consider_visiting (early): `./a/c/d': fts_info=FTS_D , fts_le
consider_visiting (late): `./a/c/d': fts_info=FTS_D , isdir=1   consider_visiting (late): `./a/c/d': fts_info=FTS_D , isdir=1
consider_visiting (early): `./a/c/d/e': fts_info=FTS_D , fts_   consider_visiting (early): `./a/c/d/e': fts_info=FTS_D , fts_
consider_visiting (late): `./a/c/d/e': fts_info=FTS_D , isdir   consider_visiting (late): `./a/c/d/e': fts_info=FTS_D , isdir
consider_visiting (early): `./a/c/d/e': fts_info=FTS_DP, fts_   consider_visiting (early): `./a/c/d/e': fts_info=FTS_DP, fts_
consider_visiting (late): `./a/c/d/e': fts_info=FTS_DP, isdir   consider_visiting (late): `./a/c/d/e': fts_info=FTS_DP, isdir
consider_visiting (early): `./a/c/d': fts_info=FTS_DP, fts_le   consider_visiting (early): `./a/c/d': fts_info=FTS_DP, fts_le
consider_visiting (late): `./a/c/d': fts_info=FTS_DP, isdir=1   consider_visiting (late): `./a/c/d': fts_info=FTS_DP, isdir=1
consider_visiting (early): `./a/c': fts_info=FTS_DP, fts_leve   consider_visiting (early): `./a/c': fts_info=FTS_DP, fts_leve
consider_visiting (late): `./a/c': fts_info=FTS_DP, isdir=1 i   consider_visiting (late): `./a/c': fts_info=FTS_DP, isdir=1 i
consider_visiting (early): `./a/p': fts_info=FTS_D , fts_leve   consider_visiting (early): `./a/p': fts_info=FTS_D , fts_leve
consider_visiting (late): `./a/p': fts_info=FTS_D , isdir=1 i | consider_visiting (late): `./a/p': fts_info=FTS_D , isdir=1 i
consider_visiting (early): `./a/p/c': fts_info=FTS_D , fts_le | consider_visiting (early): `./a/p': fts_info=FTS_DP, fts_leve
consider_visiting (late): `./a/p/c': fts_info=FTS_D , isdir=1 <
consider_visiting (early): `./a/p/c': fts_info=FTS_DP, fts_le <
consider_visiting (late): `./a/p/c': fts_info=FTS_DP, isdir=1 <
consider_visiting (early): `./a/p': fts_info=FTS_DP, fts_leve <
consider_visiting (late): `./a/p': fts_info=FTS_DP, isdir=1 i   consider_visiting (late): `./a/p': fts_info=FTS_DP, isdir=1 i
consider_visiting (early): `./a': fts_info=FTS_DP, fts_level=   consider_visiting (early): `./a': fts_info=FTS_DP, fts_level=
consider_visiting (late): `./a': fts_info=FTS_DP, isdir=1 ign   consider_visiting (late): `./a': fts_info=FTS_DP, isdir=1 ign
consider_visiting (early): `./c': fts_info=FTS_D , fts_level=   consider_visiting (early): `./c': fts_info=FTS_D , fts_level=
consider_visiting (late): `./c': fts_info=FTS_D , isdir=1 ign | consider_visiting (late): `./c': fts_info=FTS_D , isdir=1 ign
consider_visiting (early): `./c/a': fts_info=FTS_D , fts_leve   consider_visiting (early): `./c/a': fts_info=FTS_D , fts_leve
consider_visiting (late): `./c/a': fts_info=FTS_D , isdir=1 i | consider_visiting (late): `./c/a': fts_info=FTS_D , isdir=1 i
consider_visiting (early): `./c/a/c': fts_info=FTS_D , fts_le   consider_visiting (early): `./c/a/c': fts_info=FTS_D , fts_le
consider_visiting (late): `./c/a/c': fts_info=FTS_D , isdir=1   consider_visiting (late): `./c/a/c': fts_info=FTS_D , isdir=1
consider_visiting (early): `./c/a/c/g': fts_info=FTS_D , fts_   consider_visiting (early): `./c/a/c/g': fts_info=FTS_D , fts_
consider_visiting (late): `./c/a/c/g': fts_info=FTS_D , isdir   consider_visiting (late): `./c/a/c/g': fts_info=FTS_D , isdir
consider_visiting (early): `./c/a/c/g/f': fts_info=FTS_D , ft   consider_visiting (early): `./c/a/c/g/f': fts_info=FTS_D , ft
consider_visiting (late): `./c/a/c/g/f': fts_info=FTS_D , isd   consider_visiting (late): `./c/a/c/g/f': fts_info=FTS_D , isd
consider_visiting (early): `./c/a/c/g/f': fts_info=FTS_DP, ft   consider_visiting (early): `./c/a/c/g/f': fts_info=FTS_DP, ft
consider_visiting (late): `./c/a/c/g/f': fts_info=FTS_DP, isd   consider_visiting (late): `./c/a/c/g/f': fts_info=FTS_DP, isd
consider_visiting (early): `./c/a/c/g': fts_info=FTS_DP, fts_   consider_visiting (early): `./c/a/c/g': fts_info=FTS_DP, fts_
consider_visiting (late): `./c/a/c/g': fts_info=FTS_DP, isdir   consider_visiting (late): `./c/a/c/g': fts_info=FTS_DP, isdir
consider_visiting (early): `./c/a/c': fts_info=FTS_DP, fts_le   consider_visiting (early): `./c/a/c': fts_info=FTS_DP, fts_le
consider_visiting (late): `./c/a/c': fts_info=FTS_DP, isdir=1   consider_visiting (late): `./c/a/c': fts_info=FTS_DP, isdir=1
consider_visiting (early): `./c/a': fts_info=FTS_DP, fts_leve   consider_visiting (early): `./c/a': fts_info=FTS_DP, fts_leve
consider_visiting (late): `./c/a': fts_info=FTS_DP, isdir=1 i   consider_visiting (late): `./c/a': fts_info=FTS_DP, isdir=1 i
consider_visiting (early): `./c': fts_info=FTS_DP, fts_level=   consider_visiting (early): `./c': fts_info=FTS_DP, fts_level=
consider_visiting (late): `./c': fts_info=FTS_DP, isdir=1 ign   consider_visiting (late): `./c': fts_info=FTS_DP, isdir=1 ign
consider_visiting (early): `.': fts_info=FTS_DP, fts_level= 0   consider_visiting (early): `.': fts_info=FTS_DP, fts_level= 0
consider_visiting (late): `.': fts_info=FTS_DP, isdir=1 ignor   consider_visiting (late): `.': fts_info=FTS_DP, isdir=1 ignor
./c/a/c                             ./c/a/c

Nếu bạn để ý, có một lỗ hổng trong cách tiếp cận của Stephane mà tôi không có. Ngay cả với mận. Tôi nghĩ rằng điều này cho thấy phương pháp của anh ta là tránh làm việc thêm trong việc đi vào các thư mục mà nếu không thì nên bỏ qua.


Điều đó vẫn gây ra findxuống các pthư mục mặc dù.
Stéphane Chazelas

Có, vì -prunekhông thể cắt tỉa trong tình huống này, lọc có thể là tùy chọn duy nhất còn lại.
Bohr

@StephaneChazelas, một cái gì đó như thế này sẽ giải quyết vấn đề của bạn? find -mindepth 3 -type d -path '*/p/*' -prune -o -name c -print.
slm

Vâng, điều đó hoàn toàn chính xác. Tôi quên tôi có thể cắt tỉa con đường! Cảm ơn bạn! (Điều này nên được thêm vào câu trả lời của bạn.)
Bohr

@Bohr, chỉ cần cập nhật nó.
slm

4

Với cả FreeBSD và GNU find(là một vài trong số các triển khai hỗ trợ -mindepth), bạn -prunesẽ chỉ cắt tỉa các pthư mục ở độ sâu 3 hoặc sâu hơn. Cả findtài liệu FreeBSD và GNU đều làm cho nó khá rõ ràng (ở đây là tài liệu GNU):

-- Option: -mindepth levels
    Do not apply any tests or actions at levels less than LEVELS (a
    non-negative integer).  `-mindepth 1' means process all files
    except the command line arguments.

Bạn luôn có thể làm theo cách tiêu chuẩn thay thế:

find . -type d -name p -prune -o -path './*/*/*' -name c -print

( -mindepth-orkhông phải là findvị từ chuẩn , bỏ qua (các) thư mục cũng không phải là tiêu chuẩn).

Hoặc với zsh:

setopt extendedglob
printf '%s\n' ^p/^p/(^p/)#c

Chỉ tò mò, tại sao bạn nói cách này là cách "chuẩn"? Bởi vì bạn đã sử dụng -othay vì -or?
slm

@slm, câu cuối nên làm cho rõ.
Stéphane Chazelas

Tôi thấy ghi chú trong trang man bây giờ, nó nói -orgiống như -onhưng không tuân thủ POSIX.
slm

0

Theo trang người đàn ông tìm:

 -prune True;  if  the  file is a directory, do not descend into it. If
        -depth is given, false; no  effect.

Vì vậy, trong trường hợp cụ thể của bạn, tôi sẽ làm một cái gì đó như:

 find a/* -mindepth 2  -type f -print

Nhưng tất nhiên không phải lúc nào cũng là một giải pháp dễ dàng như vậy.


Xin lỗi tôi nên làm cho nó rõ ràng hơn!
Bohr
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.