Có thể lồng một 'find -exec' trong một 'find -exec' khác không?


14

Một cái gì đó như sau là những gì tôi đang theo đuổi, nhưng mã của tôi không hoạt động, bất kể tôi thoát ra sao {}+ ;

find ./ -maxdepth 1 -type d -name '.*' -exec \
    find {} -maxdepth 1 -type f -name '*.ini' -exec \
        md5sum \{\} \\; \;

Sau khi xem câu hỏi Unix - & - Linux này , tôi thấy rằng đoạn mã sau hoạt động, nhưng nó không được lồng tìm như vậy và tôi nghi ngờ có một cách tốt hơn để thực hiện công việc đặc biệt này.

find ./ -maxdepth 1 -type d -name '.*' \
-exec bash -c 'for x; do
    find "$x" -maxdepth 1 -type f -name "*.ini" \
    -exec md5sum \{\} \;; \
done' _ {} \+

Có một số cách để làm tổ find -execmà không cần phải gọi một cái vỏ (như trên), với tất cả các trích dẫn và thoát hạn chế của nó?

Hoặc điều này có thể được thực hiện trực tiếp trong một lệnh find, sử dụng hỗn hợp nhiều tham số của nó không?


4
Mặc dù có thể thực hiện những gì bạn yêu cầu, khi mọi thứ trở nên phức tạp, tôi chuyển sang tập lệnh shell hoặc Perl. Đoạn mã thứ hai của bạn thực hiện khá nhiều việc này, chỉ với mã script shell. Anh hùng một lót là giải trí, nhưng họ khó hiểu, và do đó khó duy trì. Trừ khi đây là một thỏa thuận một lần mà bạn vẫn bằng cách nào đó cuối cùng trở nên giỏi, tôi không thể thấy một lý do chính đáng để làm điều đó ngoài thử thách trí tuệ.
Warren Young

1
@Warren Young: Tôi chắc chắn không nghĩ rằng khái niệm này là phức tạp, nhưng tôi giả sử bạn có nghĩa là không đơn giản cách để làm với find, nhưng nếu findkhông thể làm được điều này, thì tại sao findrất được kính trọng (?) Như tool- sử dụng để tìm tập tin? ... Tôi đã phát hiện ra rằng nó find ./ -maxdepth 2 -path '.*/*.ini' -type f -exec md5sum {} \+hoạt động tốt trong tình huống của tôi (tài liệu tham khảo của jw013 -pruneđã dẫn tôi đến điều này trong trang man), nhưng tôi tự hỏi liệu đây có phải là một phương pháp mạnh mẽ (nói chung). Tôi chưa bao giờ thực sự sử dụng find(trong chưa đầy một năm Linux) vì locateđã làm gần như tất cả những gì tôi cần, vì vậy đó là lãnh thổ chưa biết.
Peter.O

1
Bài -pathkiểm tra là chính xác những gì tôi sẽ đề nghị. Với điều này, bạn sẽ có thể làm tất cả những gì bạn muốn (xin lỗi vì hiệp hội Ace Of Base;))
rozcietrzewiacz

Câu trả lời:


8

Tôi sẽ thử sử dụng một tìm kiếm như:

find .*/ -maxdepth 1 -type f -name '*.ini' -execdir md5sum {} +

hoặc thậm chí (không có gì findcả, chỉ cần vỏ

md5sum .*/*.ini

mặc dù điều này thiếu -type fkiểm tra nên chỉ hoạt động nếu bạn không có thư mục / tệp không kết thúc .ini. Nếu bạn có thể sử dụng

for x in .*/*.ini; do 
    if [ -f "$x" ]; then 
        md5sum "$x"
    fi
done

tuy nhiên sẽ mất lợi thế khi chỉ cần một lệnh gọi md5sum.

Biên tập

Đối với một phương pháp xích chung và an toàn find, bạn có thể làm một cái gì đó như

find <paths> <args> -print0 | xargs -0 -I{.} find {.} <args for second find> [etc.]

Tôi gặp lỗi với -f(f?), Và sau đó là một lỗi khác với -execdir.. Khi tôi thay thế -execdir bằng -exec và / hoặc cũng thay thế md5sum bằng bản in, tôi không nhận được gì ..
Peter.O

Cảm ơn, vì sự thay thế ... nhưng tôi sẽ làm được nhiều hơn sau khi sử dụng find... Tôi không muốn ví dụ này được giải quyết, tôi đang tìm hiểu sâu về các cách tìm kiếm .. . có lẽ có nhiều lông tơ hơn fu tìm thấy .. (Tôi không biết, vì tôi hầu như chưa bao giờ sử dụng nó), và đây là tình huống đầu tiên tôi thực sự muốn sử dụng nó (thực sự cho các tệp hình ảnh) và -exec tính năng tôi đã nghe rất nhiều về dường như không toàn năng như đại diện của nó (?) ám chỉ ... (+1 cho các lựa chọn thay thế) .. nhưng findví dụ của bạn không hoạt động (vẫn )
Peter.O

Tôi nhận được lỗi này cho findlệnh: ... find: The relative path ~ / bin 'được bao gồm trong biến môi trường PATH, không an toàn khi kết hợp với hành động -execdir của find. Vui lòng xóa mục nhập đó khỏi $ PATH` .... Vì vậy, có thể nó sẽ hoạt động, nhưng tôi phải nói rằng tôi đã cố gắng loại bỏ mục đó ~ / bin trong một thời gian bây giờ ... Tôi sẽ phải mất nhiều hơn nhìn nghiêm túc vào nó ... tôi không biết tôi đã đặt nó ở đâu ... bất kỳ ý tưởng nào có thể ẩn giấu; the ~/binPATH của tôi
Peter.O

Tôi nghĩ rằng sức mạnh của findđược đánh giá cao nhất trong các tình huống không thể được thực hiện hoàn toàn bằng các quả cầu, nhưng vì những tình huống đó rất hiếm nên tôi thường không cần tìm nhiều.
jw013

Được rồi .. đó là một điểm thú vị và tốt (về việc sử dụng các quả cầu) ...
Peter.O

2

Vấn đề ban đầu của bạn không yêu cầu gọi tìm đệ quy nhưng tôi cho rằng đó không phải là vấn đề.

Tôi tin rằng không thể gọi tìm đệ quy theo cách bạn muốn.

Sau đây không phải là gọi find đệ quy (hoặc lồng nhau, bất kể nó được gọi là gì), nhưng bạn không thể lấy một tập kết quả của lần tìm đầu tiên và đưa nó đến lần thứ hai? Đây là cách tôi làm theo bản năng:

find `find ./ -maxdepth 1 -type d -name '.*'` \
    -maxdepth 1 -type f -name '*.ini' -exec md5sum {} \;

Bạn cũng có thể sử dụng xargsđể thực hiện tìm kiếm thứ hai.

Cập nhật:

Tôi muốn thêm rằng vì hầu hết các tiện ích UNIX có một số đối số tên tệp thay vì một, bạn thường có thể tránh -exechoàn toàn:

md5sum `find \`find ./ -maxdepth 1 -type d -name '.*'\` -maxdepth 1 -type f -name '*.ini'`

Khi lồng ngược backticks bạn chỉ cần thêm dấu gạch chéo ngược \trước những cái bên trong.

Nếu chúng ta tưởng tượng rằng md5sumchỉ cần một đối số tên tệp, chúng ta luôn có thể gói nó trong một forvòng lặp:

for f in `find \`find ./ -maxdepth 1 -type d -name '.*'\` -maxdepth 1 -type f -name '*.ini'`
do
    md5sum $f
done

Lưu ý rằng điều này trở nên khó khăn hơn nếu tên tệp / thư mục bắt đầu bằng -hoặc chứa một khoảng trắng có liên quan. Các tiện ích UNIX không chơi độc đáo với chúng. Trong trường hợp đó thêm ./, --hoặc trích dẫn là cần thiết.

Rõ ràng ví dụ ban đầu không phải là một ví dụ tốt, bởi vì chúng ta chỉ có thể làm:

md5sum .*/*.ini

1
Bạn đã đưa ra một cái nhìn tổng quan về tình huống, nhưng tất cả các findphương thức được hiển thị đều gặp lỗi khi tệp / thư mục chứa khoảng trắng ... Hoạt md5sum .*/*.iniđộng tốt ... Tôi bắt đầu có cảm giác chung rằng * Warren Young * nhận xét về những điều trở nên 'phức tạp' findxảy ra sớm trong trò chơi :), nhưng tôi cho rằng findnó sẽ tự xảy ra khi các bài kiểm tra điều kiện phức tạp hơn, nhưng theo như lồng ghép -exec, tôi đã bỏ khá nhiều ý tưởng, vì có vẻ như có nhiều cách đơn giản hơn để làm điều đó .. (nhưng perl không "đơn giản" với tôi (chưa) ...
Peter.O

0

Ít nhất tôi đã quản lý để lồng 2 lệnh tìm:

find ~ -maxdepth 1 -type d -name '.*' -execdir \
    find {} -maxdepth 1 -type f -name '*.ini' \;

Nhưng tôi đã không giải quyết để gọi một -exec (dir) khác - cuộc gọi từ đó.


Vâng, đó chính xác là vấn đề của tôi :)
Peter.O

Có, nhưng không lồng 3 không giống như không lồng 2. :)
người dùng không biết
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.