2008-11-20 25 views

Trả lời

109

Công việc diễn giải các biểu tượng ống như một hướng dẫn để chạy nhiều quy trình và ống đầu ra của một quá trình vào đầu vào của quá trình khác là trách nhiệm của vỏ (/ bin/sh hoặc tương đương).

Trong ví dụ của bạn, bạn có thể chọn để sử dụng vỏ cấp cao nhất của bạn để thực hiện các đường ống như vậy:

find -name 'file_*' -follow -type f -exec zcat {} \; | agrep -dEOE 'grep' 

Xét về hiệu quả này dẫn đến chi phí một lời khẩn cầu tìm kiếm, nhiều invocations của zcat, và một kêu gọi đồng ý.

Điều này sẽ dẫn đến chỉ một quá trình đồng ý duy nhất được sinh ra và sẽ xử lý tất cả đầu ra được tạo ra bởi vô số lời gọi của zcat.

Nếu bạn vì một lý do muốn gọi aGrep nhiều lần, bạn có thể làm:

find . -name 'file_*' -follow -type f \ 
    -printf "zcat %p | agrep -dEOE 'grep'\n" | sh 

này xây dựng một danh sách các lệnh sử dụng đường ống để thực hiện, sau đó gửi chúng cho vỏ mới để thực sự được thực thi . (Bỏ qua "sh" cuối cùng là một cách hay để gỡ lỗi hoặc thực hiện các dòng lệnh khô như thế này.)

Về mặt hiệu quả, kết quả này tốn một yêu cầu tìm kiếm, một lệnh gọi sh, nhiều lệnh gọi zcat và nhiều invocations của agrep.

Giải pháp hiệu quả nhất về mặt số lời gọi lệnh là những gợi ý từ Paul Tomblin:

find . -name "file_*" -follow -type f -print0 | xargs -0 zcat | agrep -dEOE 'grep' 

... mà chi phí một lời khẩn cầu tìm kiếm, một lời kêu cầu của xargs, một vài lời gọi của zcat và một lời kêu gọi của agrep.

+1

Một ưu điểm khác của xargs là, bạn có thể tăng tốc nó với cpu đa lõi hiện đại hơn nữa, bằng cách sử dụng công tắc -P (-P 0). – flolo

+0

Vâng, các -P swich thực sự là một cách tốt đẹp để tăng tốc độ thực hiện nói chung. Thật không may, bạn chạy nguy cơ đầu ra của quá trình zcat song song đang được piped vào agrep xen kẽ, mà sẽ ảnh hưởng đến kết quả. Hiệu ứng này có thể được chứng minh bằng cách sử dụng: echo -e "1 \ n2" | xargs -P 0 -n 1 có | uniq –

+0

@Adam, tôi đã thực hiện thay đổi được đề xuất của bạn. –

13
find . -name "file_*" -follow -type f -print0 | xargs -0 zcat | agrep -dEOE 'grep' 
+0

Hy vọng để tránh -print và xargs vì lý do hiệu quả. Có lẽ đó thực sự là vấn đề của tôi: tìm không thể xử lý các lệnh đường ống thông qua -exec – someguy

+0

Điều này không hoạt động với các tệp có dấu cách trong tên của chúng; để sửa, thay thế dấu vân tay bằng -print0 và thêm tùy chọn -0 vào xargs –

+2

@someguy - Wha? Tránh xargs vì lý do hiệu quả? Gọi một thể hiện của zcat, và truyền cho nó một danh sách gồm nhiều tệp, là * xa * hiệu quả hơn việc thực thi một cá thể mới của nó cho mỗi tệp được tìm thấy. –

190

giải pháp là đơn giản: thực hiện qua sh

... -exec sh -c "zcat {} | agrep -dEOE 'grep' " \; 
+13

Những gì OP đang cố gắng hoàn thành có thể được đáp ứng với các đề xuất ở trên, nhưng đây là câu trả lời thực sự trả lời câu hỏi. Có nhiều lý do để thực hiện theo cách này - exec mạnh hơn rất nhiều so với việc chỉ hoạt động trên các tệp được trả về bằng cách tìm, đặc biệt khi kết hợp với kiểm tra. Ví dụ: tìm geda-gaf/-type d -exec bash -c 'DIR = {}; [[$ (tìm $ DIR -maxdepth 1 | xargs grep -i gia vị | wc -l) -ge 5]] && echo $ DIR '\; Sẽ trả về tất cả các thư mục trong đường dẫn tìm kiếm chứa tổng cộng hơn 5 dòng trong số tất cả các tệp trong thư mục đó chứa từ gia vị – swarfrat

+2

Câu trả lời hay nhất. Tham khảo toàn bộ đầu ra (như các câu trả lời khác được đề xuất) không giống như grep mỗi tệp. Mẹo: thay vì sh, bạn có thể sử dụng bất kỳ trình bao nào khác mà bạn muốn (tôi đã thử bằng bash và nó đang chạy ok). – pagliuca

+1

Đảm bảo không bỏ qua tùy chọn '-c'. Nếu không, bạn sẽ nhận được một thông báo lỗi "Không có tệp hoặc thư mục" gây nhầm lẫn. – asmaier

8

Bạn cũng có thể đặt đường ống đến vòng lặp while có thể thực hiện nhiều tác vụ trên tệp có kích thước find. Vì vậy, đây là một cho tìm kiếm trong jar tài liệu lưu trữ cho một tập tin lớp học java được đưa ra trong thư mục với một distro lớn jar file

find /usr/lib/eclipse/plugins -type f -name \*.jar | while read jar; do echo $jar; jar tf $jar | fgrep IObservableList ; done 

vấn đề mấu chốt là rằng while vòng lặp chứa nhiều lệnh tham khảo thông qua vào tên tập tin phân cách bằng dấu chấm phẩy và các lệnh này có thể bao gồm các đường ống. Vì vậy, trong ví dụ đó, tôi lặp lại tên của tệp phù hợp sau đó liệt kê những gì trong bộ lọc lưu trữ cho một tên lớp đã cho. Đầu ra trông giống như:

/usr/lib/eclipse/plugins/org.eclipse.core.contenttype.source_3.4.1.R35x_v20090826-0451.jar /usr/lib/eclipse/plugins/org.eclipse.core .databinding.observable_1.2.0.M20090902-0800.jar org/eclipse/core/databinding/quan sát/danh sách/IObservableList .class /usr/lib/eclipse/plugins/org.eclipse.search.source_3.5.1. r351_v20090708-0800.jar /usr/lib/eclipse/plugins/org.eclipse.jdt.apt.core.source_3.3.202.R35x_v20091130-2300.jar /usr/lib/eclipse/plugins/org.eclipse.cvs.source_1.0.400.v201002111343.jar /usr/lib/eclipse/plugins/org.eclipse.help.appserver_3.1.400.v20090429_1800.jar

trong bash shell của tôi (xubuntu10.04/xfce) nó thực sự làm cho tên lớp phù hợp được in đậm như là fgrep làm nổi bật chuỗi phù hợp; điều này giúp bạn dễ dàng quét danh sách hàng trăm tệp jar được tìm kiếm và dễ dàng xem bất kỳ kết quả phù hợp nào.

trên cửa sổ bạn có thể làm điều tương tự với:

for /R %j in (*.jar) do @echo %j & @jar tf %j | findstr IObservableList 

lưu ý rằng trong đó trên cửa sổ tách lệnh là '&' không ';' và rằng '@' triệt tiêu tiếng vọng của lệnh để đưa ra một đầu ra gọn gàng giống như đầu ra tìm thấy linux ở trên; mặc dù findstr không làm cho chuỗi phù hợp được in đậm, do đó bạn phải nhìn gần hơn một chút ở đầu ra để xem tên lớp phù hợp. Nó chỉ ra rằng các cửa sổ 'cho' lệnh biết khá một vài thủ thuật như vòng lặp thông qua các file văn bản ...

thưởng thức

Các vấn đề liên quan