Tôi có thể sử dụng find và grep trong một dòng không?


7

Tôi có một cấu trúc thư mục dựa trên các sự kiện.

Trong các sự kiện này, tôi có một loại tệp không hoặc không chứa mẫu mà tôi cần tìm kiếm. Các kết quả tích cực tôi muốn lưu trữ trong một tệp riêng biệt.

Cách tiếp cận đầu tiên của tôi là:

find . /EVENT*/'filename' | grep 'searchtext' head -2 > error_file

nhưng điều đó dường như không hoạt động. Tôi đã nói rằng không thể kết hợp findgreptheo cách này, vậy tôi cần phải làm như thế nào?


Lưu ý rằng những gì bạn đang làm ở đây là ( khoảng ; điều này không đúng về mặt kỹ thuật 100%, nhưng nó đủ gần để xấp xỉ đơn hàng đầu tiên để cho bạn biết ý tưởng thực sự đang diễn ra) trước tiên find . /EVENT*/'filename', sau đó lấy bất cứ lệnh nào in ra theo tiêu chuẩn của nó đầu ra (trong trường hợp findtheo mặc định sẽ là một danh sách các tên tệp) và chuyển thành đầu vào tiêu chuẩn vào lệnh grep 'searchtext' head -2(điều này không có ý nghĩa nhiều như grepsẽ không nhìn vào stdin khi được đặt tên tệp), sau đó chuyển hướng đầu ra tiêu chuẩn của greptập tin error_file.
một CVn

Nếu tôi giải thích nó một cách chính xác, có vẻ như có một sự mở rộng giống như toàn cầu trong /EVENT*/'filename'. Tôi không chắc làm thế nào để làm điều này với findvà AFAIK bashkhông thể làm điều này. Tất cả các câu trả lời cho đến nay đã bỏ lỡ điều này.
Sparhawk

Câu trả lời:


14

Đây là một mô hình chung:

find /directory/containing/files -type f -exec grep -H 'pattern_to_search' {} +

Ở đây lúc đầu findsẽ tìm kiếm tất cả các tệp trong thư mục chứa các tệp cần thiết, bạn cũng có thể sử dụng các ký tự đại diện, ví dụ *.txtđể chỉ tìm các tệp kết thúc bằng .txt. Trong trường hợp đó, lệnh sẽ là:

find /directory/containing/files -type f -name "*.txt" -exec grep -H 'pattern_to_search' {} +

Sau khi tìm thấy các tệp cần thiết, chúng tôi đang tìm kiếm mẫu mong muốn trong các tệp đó bằng cách sử dụng -exec grep -H 'pattern_to_search' {} +( -Hsẽ in tên tệp nơi tìm thấy mẫu đó). Ở đây bạn có thể nghĩ đến việc {}chứa các tệp cần tìm và +cần được sử dụng ở cuối -execđể nó -execsẽ được rẽ nhánh một lần tức là grepsẽ tìm kiếm như thể là lệnh grep -H 'pattern_to_search' file_1.txt file_2.txt file_3.txt.


Được rồi - Tôi đoán đây là lý do: superuser.com/questions/140689/, Nếu cuối cùng chỉ có một tệp trong trận đấu, grep sẽ không in tên tệp, vì vậy việc thêm /dev/nullđảm bảo có ít nhất hai nếu có trận đấu. Nhưng sử dụng -Hcó vẻ như một phương pháp phong cách chuẩn hơn, ít zany-hack hơn (và ít gõ hơn). Tôi sẽ đổi nó thành cái đó;)
goldilocks

Tôi cũng nghĩ bạn cần '{}', không đơn giản {}. Nếu không thì tôi nhận được missing argument to -exec.
goldilocks

@goldilocks - bạn không cần phải trích dẫn điều đó.
mikeserv

@mikeerv Hmmmph, có vẻ như đó là một vấn đề vỏ - chính xác điều tương tự dưới bash là tốt. Tôi nhớ đã bị nhầm lẫn về điều này một thời gian trước, tôi đoán đó là khi tôi bắt đầu sử dụng cá làm mặc định của mình.
goldilocks

Tôi cũng sẽ đi tìm một trích dẫn thay vì nhân đôi, trượt tuyết để tránh mọi nội suy bất ngờ
roaima 15/03/2015

5

Một phương pháp hợp lệ khác là:

 find /directory/containing/files -type f -print0 | xargs -0 grep "test to search"

Tùy chọn print0 / tùy chọn -0 là cho phép trong trường hợp chuỗi tên tệp chứa các ký tự đặc biệt (như khoảng trắng).


Sử dụng -exec grep "test to search" {} +tên tập tin xử lý với các ký tự đặc biệt tốt. Lý do duy nhất để không sử dụng nó là một số hệ thống không hỗ trợ nó.
AKHolland

3

Và nhiều hơn nữa một cách, chỉ trong một quá trình duy nhất (không có find, -exec, xargs):

grep -r "test to search" /directory/containing/files

Vâng, với GNU grep, dù sao đi nữa. :)

ETA: Vì tôi đã được yêu cầu hiển thị grep --includetùy chọn, đây là một ví dụ tương tự với ví dụ của heemayl ("bạn cũng có thể sử dụng ký tự đại diện, ví dụ * .txt để chỉ tìm các tệp kết thúc bằng .txt"):

grep --include '*.txt*' -r "pattern to search" /directory/containing/files

Và trong khi tôi đang chỉnh sửa, vâng, đây là những lựa chọn thay thế, không phải thay thế thả xuống: Các lệnh này sẽ đọc các tệp (thông thường) thông qua các liên kết tượng trưng. (Họ sẽ không recurse thông qua các thư mục symlinked mặc dù, cho rằng bạn cần -R.) Họ cũng sẽ đọc ổ cắm, ống tên, và các tập tin thiết bị (mặc dù -D skipcó thể được thêm vào, um, bỏ qua những). Và không có cách nào grepđể có được hiệu ứng của các findtùy chọn như thế nào -mtime -2. Nếu bạn cần những thứ đó - hãy sử dụng find. Nếu bạn không, tốt, tôi sẽ tranh luận greplà một lựa chọn tốt.


2
Điều này khác ở chỗ grep sau đó tìm kiếm tất cả các tệp (đôi khi không thú vị) thay vì những tệp phù hợp với một findmẫu.
goldilocks

3
@goldilocks Chắc chắn, nếu bạn một findmẫu. Ngoại trừ, bạn có thể đưa ra các mẫu cho grep -rlà tốt; phổ biến nhất --exclude=GLOB(hoặc --include=GLOB) và --exclude-dir=GLOB, mặc dù tôi đoán bạn đôi khi cần -D skipvà / hoặc -I. Nhưng chắc chắn, nếu bạn có -mtime -2hoặc somesuch, bạn cần điều đó find. grep -rlà một lựa chọn khác, không phải là một sự thay thế.
Sidhekin 15/03/2015

@The Sidhekin: bạn nên chỉnh sửa bài đăng của mình để thêm tùy chọn --incoide. Đây là câu trả lời chính xác.
jopasserat

@jopasserat Thật sao? Những gì để --includemặc dù? Cách tiếp cận không hoạt động ban đầu không chỉ định bất kỳ. Mặc dù tôi đoán rằng tôi có thể thêm một chất tương tự vào ví dụ có thể sử dụng cũng của Heemayl
Sidhekin

Xem xét kỹ câu hỏi của OP, anh ta dường như có một loại tệp cụ thể để tìm kiếm. Vì vậy, tôi muốn nói --include = 'mẫu' với mẫu khớp với bất cứ thứ gì anh ta muốn.
jopasserat

0

Tôi sẽ giả định rằng bạn cần grep cho một mẫu cụ thể thông qua các tệp văn bản và lặp lại thông qua các thư mục con. Nếu bạn đang sử dụng GNU grep, nó khá đơn giản:

cd /to/the/top/level    
grep -r "PatternToSearch" *

Thay vì -r, bạn có thể sử dụng -Rhoặc--recursive

Bạn phải sử dụng dấu ngoặc kép nếu bạn có khoảng trắng trong mẫu tìm kiếm của bạn.

Có rất nhiều tùy chọn cho GNU grep. Chỉ cần gõ grep --helpvà bạn sẽ ngạc nhiên!


Làm thế nào để bạn yêu cầu grep chỉ xem xét các tệp phù hợp với một patter cụ thể? Nói, tên tập tin mở rộng? Đề xuất này sẽ khiến grep tìm kiếm mọi tệp trong hệ thống tệp trong thư mục này: đó không phải là điều mà câu hỏi đang cố gắng thực hiện.
GreenAsJade

Một cái gì đó như * .log nên làm. Nhân tiện, Silver Searcher sẽ tiện dụng hơn và nhanh hơn cho việc này:ag SearchWord FilePattern
Hopping Bunny
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.