Cách grep hàng ngàn tệp trong một thư mục cho hàng trăm chuỗi trong một tệp


11

Tôi đang cố gắng soạn một greptuyên bố và nó đang giết chết tôi. Tôi cũng mệt mỏi vì nhận được arguments list too longlỗi. Tôi có một tập tin, hãy gọi nó subset.txt. Nó chứa hàng trăm dòng với các chuỗi cụ thể như MO43312948. Trong thư mục đối tượng của tôi, tôi có hàng ngàn tệp và tôi cần sao chép tất cả các tệp có chứa các chuỗi được liệt kê trong subset.txtthư mục khác.

Tôi đã cố gắng bắt đầu với điều này để chỉ trả lại các tập tin phù hợp từ thư mục đối tượng.

grep -F "$(subset.txt)" /objects/*

Tôi tiếp tục nhận được `bash: / bin / grep: Danh sách đối số quá dài``


6
Tại sao bạn lại đặt "$(subset.txt)"lệnh như vậy? Đó là thay thế lệnh , sẽ làm cho shell của bạn thực thi subset.txt (như thể nó là một lệnh hoặc tập lệnh).
JigglyNaga

Câu trả lời:


23

Bạn có thể vượt qua một thư mục như một mục tiêu để grep-Rvà một tập tin của mô hình đầu vào với -f:

  -f FILE, --file=FILE
          Obtain patterns from FILE, one per line.  If this option is used
          multiple  times  or  is  combined with the -e (--regexp) option,
          search for all patterns given.  The  empty  file  contains  zero
          patterns, and therefore matches nothing.

   -R, --dereference-recursive
          Read all files under each directory,  recursively.   Follow  all
          symbolic links, unlike -r.

Vì vậy, bạn đang tìm kiếm:

grep -Ff subset.txt -r objects/

Bạn có thể lấy danh sách các tệp phù hợp với:

grep -Flf subset.txt -r objects/

Vì vậy, nếu danh sách cuối cùng của bạn không quá dài, bạn có thể thực hiện:

 mv $(grep -Flf subset.txt -r objects/) new_dir/

Nếu điều đó trả về một argument list too longlỗi, sử dụng:

grep -Flf subset.txt -r objects/ | xargs -I{} mv {} bar/

Và nếu tên tệp của bạn có thể chứa dấu cách hoặc các ký tự lạ khác, hãy sử dụng (giả sử GNU grep):

grep -FZlf subset.txt -r objects/ | xargs -0I{} mv {} bar/

Cuối cùng, nếu bạn muốn loại trừ các tệp nhị phân, hãy sử dụng:

grep -IFZlf subset.txt -r objects/ | xargs -0I{} mv {} bar/

Có thể tránh hàng ngàn mvlời mời tiềm năng với mỗi đối số: ... | xargs -0 mv -t bar/(giả sử bạn mvhỗ trợ -ttùy chọn).
David Foerster

11

sử dụng

grep -F -f subset.txt 

để nói với grep để đọc từ subset.txttập tin.

bạn có thể sử dụng find để đi bộ tập tin.

find . -type f -exec grep -F -f subset.txt {} \;

hoặc là

find . -type f -exec grep -F -f subset.txt {}  +

Bất kỳ lợi thế của việc sử dụng findthay vì -rkhác hơn là bạn thực hiện lọc bổ sung?
phk

1
@phk grep -rtìm kiếm trong các liên kết tượng trưng đến các tệp thông thường, có thể hoặc không mong muốn (nếu chúng trỏ vào cùng một cây, bạn đang tìm kiếm cùng một tệp hai lần; nếu chúng chỉ ra bên ngoài, bạn đang tìm kiếm một tệp có thể hoặc không được mong muốn).
Gilles 'SO- ngừng trở nên xấu xa'

Các phiên bản hiện đại grepcó các tùy chọn để kiểm soát sự tương tác của chúng với các liên kết tượng trưng ( man grepđể xác định các chi tiết cụ thể cho hệ thống hiện tại). Một đệ quy grepsẽ nhanh hơn rất nhiều so với việc chạy grepriêng lẻ trên mỗi tệp thông qua find.
Perry

1
@Perry bạn có chắc về điều đó? Tại sao? Ngoài ra, lưu ý rằng câu trả lời này đang được sử dụng -exec +, vì vậy nó sẽ nhóm các tệp và không chạy một grep cho mỗi tệp.
terdon

Tôi đứng sửa chữa, tôi đã không biết về ngữ nghĩa khác nhau -exec {} +vs -exec {} \;... bạn học được điều gì mới mỗi ngày (tôi vẫn thấy không có lý do tại sao một đệ quy đơn grepwont có nhanh hơn nhiều greps chạy từ finddo tạo quá trình và mô hình phân tích chi phí nhưng tôi không có số cụ thể để hỗ trợ sao lưu).
Perry

3

Nếu bạn muốn tăng tốc grep hơn nữa, bạn có thể đặt ngôn ngữ trong trình bao của mình trước khi chạy nó, tức là sử dụng "LC_ALL = c". Điều này sẽ được kế thừa thành grep và sẽ vô hiệu hóa xử lý Unicode khi không cần thiết và trong một số trường hợp có thể tăng tốc đáng kể grep. Một tài liệu blog tuyệt vời này có thể được tìm thấy tại http://www.inmotionhosting.com/support/website/ssh/speed-up-grep-searches-with-lc-all . Thủ thuật này cũng có thể tăng tốc độ bash shell script, không chỉ grep.

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.