Làm thế nào để tôi dừng một tìm kiếm từ giảm dần vào các thư mục tìm thấy?


24

Tôi muốn tìm tất cả các thư mục với một chuỗi cụ thể để tôi có thể thực hiện một tìm kiếm khác trên các tệp có trong đó.

Vì vậy, tôi không muốn lãng phí thời gian vào ./my-search-term/dir/my-search-termvv

Làm cách nào tôi có thể ngừng đệ quy khi tôi tìm thấy thư mục tìm kiếm đầu tiên của mình?


3
Bạn đã thử tìm với -prune? Từ trang man: "nếu tập tin là một thư mục, đừng đi vào nó. Nếu -depth được đưa ra, sai; không có tác dụng.
laebshade

1
@laebshade tại sao bạn không đặt câu trả lời?
jw013

@ jw013 Tôi không có thời gian để đưa ra câu trả lời sâu sắc hơn vào thời điểm đó.
laebshade

Câu trả lời:


17

Các -prunehành động làm cho findkhông tái diễn vào thư mục. Bạn có thể kết hợp nó với một hành động khác như -exec(thứ tự -prune-execkhông quan trọng, miễn là -pruneđược thực hiện theo bất kỳ cách nào).

find . -name my-search-term -prune -exec find {} … \;

Lưu ý rằng lồng findbên trong find -execcó thể có một chút vấn đề: bạn không thể sử dụng -execbên trong find, bởi vì bộ kết thúc sẽ được xem như là một bộ kết thúc bởi bên ngoài find. Bạn có thể giải quyết vấn đề đó bằng cách gọi shell, nhưng hãy cẩn thận khi trích dẫn.

find . -name my-search-term -prune -exec sh -c '
    find "$@" … -exec … {\} +
' _ {} +

Các dấu ngoặc trong lệnh đầu tiên của bạn có cần thiết không? -prunetrả về true và có thể được đặt trước -exec.
rozcietrzewiacz

@rozcietrzewiacz Không, chúng không cần thiết. Thói quen có một -otrong đó, tôi đoán. Và tôi đoán đặt -prunetrước -execlà dễ đọc hơn.
Gilles 'SO- ngừng trở nên xấu xa'

Cảm ơn, đã không sử dụng -prunetùy chọn trước.
haridsv

Trong trường hợp sử dụng của tôi, lệnh này: mkdir -p x1 x2; touch x1/x11 x1/x12 x2/x21 x2/x22; find . -name 'x1*' -exec rm -rf {} \;đưa ra lỗi : find: ./x1: No such file or directory. Giải pháp là thêm -prunevào cuối findlệnh.
haridsv

(1) Một số phiên bản findmở rộng {}ngay cả khi nó xuất hiện dưới dạng chuỗi con của đối số -exec. Một phiên bản như vậy findsẽ bóp nghẹt lệnh thứ hai của bạn, bởi vì lệnh {}bên trong find(trong lệnh shell) sẽ được thay thế bằng tên của thư mục được tìm thấy ở bên ngoài find. Bạn có thể khắc phục điều đó bằng cách nói find . -name my-search-term -prune -exec sh -c 'find "$0" … -exec … "{"} +' {} \; , bằng cách sử dụng "{"}, cái vỏ sẽ biến thành {}. Tiết (Cont'd)
Scott

6

- giải pháp trần -

Nếu bạn muốn findbỏ qua nội dung của thư mục tìm thấy, nhưng tiếp tục tìm kiếm trong các thư mục khác, hãy sử dụng -prunenhư @laebshade đề xuất. Lệnh đầy đủ sẽ trông giống như

 find . -type d -name somename -prune -exec ...

Mặt khác, nếu bạn muốn findhoàn toàn ngừng tìm kiếm và sau khi tìm thấy thư mục phù hợp đầu tiên, thì thứ bạn đang tìm kiếm là -quit(có sẵn từ phiên bản 4.2.3của GNU find). Cái này khó sử dụng hơn một chút, vì nó tạo findra lối thoát ngay lập tức - vì vậy -quitphải được đặt ở cuối lệnh:

find . -type d -name somename -exec ... -quit

Để điều này hoạt động như mong đợi, người ta phải đảm bảo rằng -exectrả về đúng (nói cách khác, trạng thái bằng không ). Nếu bạn muốn trạng thái thoát -execbị bỏ qua, để -quitluôn hoạt động, bạn cần một mẹo nhỏ:

find . -type d -name somename \( -exec ... -o -true \) -quit

hoặc là

find . -type d -name somename \( -exec ... -o -quit \)

hoặc là

find . -type d -name somename \( -exec ... , -quit \) # a comma before -quit

- một số giải thích -

Điều quan trọng nhất về cách thức findhoạt động là tất cả các hành động ("kiểm tra") được coi là các vị từ logic được diễn giải từ trái sang phải. Do đó, hành động cuối cùng (ví dụ -quit) sẽ chỉ được thực hiện nếu toàn bộ phần trước không trả về false . Theo mặc định, tất cả các bài kiểm tra được nối với "AND" hợp lý, -otùy chọn thay đổi khớp thành "HOẶC".

Một yếu tố khó khăn -ofindcó thể "tối ưu hóa" lệnh của bạn và không chạy -execphần đó nếu bạn chỉ gõ

find . -type d -name somename -exec ... -o -quit

Để đối phó với điều đó, bạn có thể buộc findphải đánh giá tất cả các vị từ được gọi là "HOẶC", bằng cách đặt chúng trong ngoặc đơn.

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.