Làm cách nào để tìm các tệp chứa hai chuỗi với nhau trong Linux?


11

Tôi muốn tìm các tệp chứa hai chuỗi với nhau, ví dụ tệp chứa cả hai string1string2.

Tôi muốn đường dẫn đầy đủ của các tập tin trong đầu ra. Tôi không muốn thấy cảnh báo "cho phép từ chối".

Câu trả lời:


15
grep -l string2 `grep -l string1 /path/*`

giống như

grep -l string2 $(grep -l string1 /path/*)

Chỉnh sửa: đây là lý do tại sao grep string1 /path/* | grep string2tôi không làm những gì tôi nghĩ alwbtc muốn.

$ cd /tmp
$ cat a
apples
oranges
bananas
$ cat b
apples
mangoes
lemons
$ cat c
mangoes
limes
pears
$ cd ~
$ grep apples /tmp/* | grep mangoes
$

Không tìm thấy gì, nhưng tệp b chứa cả hai chuỗi.

Đây là những gì tôi nghĩ alwbtc muốn

$ grep -l apples $(grep -l mangoes /tmp/*)
/tmp/b

1
Đây là một giải pháp gọn gàng và hữu ích hơn của tôi. Đối với những người muốn biết những gì đang xảy ra ở đây (tôi phải mất một chút để tìm hiểu), anh ta sử dụng -ltùy chọn để trả về tên tệp thay vì các dòng. Sau đó, anh ta sử dụng ký hiệu đô la hoặc dấu ngoặc kép để chuyển danh sách đó làm FILEđối số vào grep thứ hai. Điều này cho phép grep thứ hai tìm kiếm toàn bộ từng tệp được tìm thấy thay vì các dòng riêng lẻ như trong giải pháp của tôi.
embedded.kyle

Bạn đã bỏ lỡ một -ltùy chọn cho cả hai lệnh được coi là bằng nhau.
pong

2

Ống này grepsang ống khác:

grep "string1" /path/to/files/* | grep "string2"


5
Nếu hai chuỗi nằm trên các dòng khác nhau trong tệp, điều này sẽ không hoạt động.
RedGrittyBrick

1
Tôi không biết có yêu cầu họ phải ở cùng một dòng @RedGrittyBrick
slhck

@slhck: Tôi đã cập nhật câu trả lời của mình để hiển thị những gì tôi nghĩ alwbtc muốn và tại sao câu trả lời này không làm điều đó. Tất nhiên, tôi có thể đã hiểu nhầm những gì alwbtc muốn và nhúng.kyle có thể đã hiểu đúng - mặc dù tôi nghi ngờ là không.
RedGrittyBrick

1

Đây là lệnh tương đương với câu trả lời của RedGrittyBrick :

ack string2 $(ack string1 -l)

Hoạt động theo cùng một cách (ngoại trừ acktheo mặc định tìm kiếm thư mục hiện tại theo cách đệ quy). Nội dung trong các $()tìm kiếm string1nhưng -lchỉ xuất ra tên tệp nơi tìm thấy chuỗi đó. Sau đó chúng được truyền dưới dạng đối số vào lệnh bên ngoài, có nghĩa string2là chỉ được tìm kiếm trong danh sách các tệp đó.


0
comm -12 <(grep --fixed-strings --files-with-matches "STRING1" /path/to/files/* 2>/dev/null | sort) <(grep --fixed-strings --files-with-matches "STRING1" /path/to/files/* 2>/dev/null | sort)

hoặc ít dư thừa:

search_files () { str="$1"; shift; grep -Fl "$str" "$@" 2>/dev/null | sort; }
comm -12 <(search_files "STRING1" /path/to/files/*) <(sf "STRING2" /path/to/files/*)

Điều này sẽ hoạt động nếu các chuỗi nằm trên các dòng khác nhau của cùng một tệp và cũng sẽ tránh các kết quả dương tính giả nếu tên tệp chứa một trong các chuỗi.


0

Để giải thích về giải pháp của @ RedGrittyBrick, một thiếu sót khi chạy lệnh không giám sát cộng với để chặn đầu ra lỗi như dự định và để tìm các tệp đệ quy bạn có thể xem xét

grep -l 'STRING1' $(! grep -lrs 'STRING2' /absolute/path/to/search/dir && echo /dev/null)

-stùy chọn sẽ chặn thông báo lỗi
-rtùy chọn cho phép tìm kiếm các chuỗi trong các thư mục được lồng tùy ý
!kết hợp với && echo /dev/nullđảm bảo rằng lệnh sẽ không bị treo. Mặt khác, nếu inner grepkhông tìm thấy bất kỳ tệp nào, nó sẽ không xuất ra bất cứ thứ gì do đó outer grepsẽ chờ vô thời hạn đầu vào để tìm kiếm. Giải pháp này xuất ra /dev/nulltrong những trường hợp này vì vậy outer grepsẽ tìm kiếm STRING1/dev/nullnơi mà nó được cho là không tìm thấy gì.


0

Tôi đang tìm kiếm một cách mở rộng để làm 2 hoặc nhiều chuỗi và đến với điều này:

grep -rl string1 path-to-files | xargs grep -l string2 | xargs grep -l string3

Grep đầu tiên tìm đệ quy tên của các tệp chứa string1bên trong path-to-files.

Các kết quả được dẫn vào xargsđể chạy một hoặc nhiều lệnh grep trên các tệp đó string2.

Các kết quả sau đó được chuyển sang một xargslệnh khác cho string3- nó giống như xargscuộc gọi đầu tiên , nhưng tìm kiếm một chuỗi khác.

Việc sử dụng xargssẽ tránh được các vấn đề khi có quá nhiều kết quả mà dòng lệnh kết quả từ việc sử dụng back-tick quá dài.

Để tránh các cảnh báo, chúng tôi có thể chuyển hướng stderrđến /dev/null:

grep -rl string1 path-to-files  2>/dev/null | xargs grep -l string2

Không cần thiết cho các cuộc gọi grep tiếp theo vì string1đã được tìm thấy bên trong tệp nên các quyền được biết là tố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.