Lệnh Grep để tìm tệp chứa chuỗi văn bản và di chuyển chúng


15

Tôi có thể định vị các tệp trong một thư mục chứa một chuỗi văn bản cụ thể bằng lệnh này:

grep -lir 'string' ~/directory/*

Làm cách nào để di chuyển các tệp xuất hiện trong kết quả trên sang vị trí khác?


Nó đây rồi grep -i -Z -r -l 'string' . | xargs -I{} mv {} ./folder_name
Alan Dong

Câu trả lời:


10

Như mọi khi, hãy cẩn thận grep -r. -rkhông phải là một tùy chọn tiêu chuẩn và trong một số triển khai như tất cả các phiên bản GNU gần đây grep, nó tuân theo các liên kết tượng trưng khi hạ xuống cây thư mục, thường không phải là điều bạn muốn và có thể có ý nghĩa nghiêm trọng nếu có một liên kết tượng trưng đến "/ "Ở đâu đó trong cây thư mục.

Trong triết lý Unix, bạn sử dụng một lệnh để tìm kiếm các thư mục cho các tệp và một lệnh khác để xem nội dung của nó.

Sử dụng các công cụ GNU, tôi sẽ làm:

xargs -r0 --arg-file <(find . -type f -exec grep -lZi string {} +
  ) mv -i --target-directory /dest/dir

Nhưng ngay cả khi đó, hãy cẩn thận với các điều kiện chủng tộc và các vấn đề bảo mật có thể xảy ra nếu bạn chạy nó với tư cách một người dùng trên một thư mục có thể ghi bởi một số người dùng khác.


điều này mang lại cho tôi lỗi tìm: `grep 'bị chấm dứt bởi tín hiệu 13. có ý tưởng nào đang xảy ra không?
Reena Parekh

@ReenaParekh, đó sẽ là một SIGPIPE. Điều đó sẽ chỉ xảy ra nếu xargsthoát ra trước khi đọc đến cuối tệp arg của nó, điều không nên xảy ra trừ khi xargs bị tự sát hoặc thất bại vì bất kỳ lý do nào trong trường hợp tôi cũng mong bạn gặp lỗi về điều đó.
Stéphane Chazelas

15

Sử dụng xargstrong buổi hòa nhạc với mvcú pháp thứ ba:mv [OPTION]... -t DIRECTORY SOURCE...

grep -lir 'string' ~/directory/* | xargs mv -t DEST

Hãy cẩn thận về các tập tin có chứa các ký tự đặc biệt (dấu cách, dấu ngoặc kép). Nếu đây là trường hợp của bạn, việc lọc danh sách bằng sed(thêm dấu ngoặc kép quanh tên tệp với s/^/'/;s/$/'/) có thể giúp ích, nhưng bạn phải chắc chắn, những trích dẫn này sẽ không xuất hiện trong tên tệp. GNU grep-Z/ --nulltùy chọn để kết thúc tên tệp NUL.

Một thay thế cho cú pháp thứ ba cho mvviệc sử dụng xargsvới chuỗi giữ chỗ ( -I).

Một tùy chọn khác là thay thế lệnh - $( )hoặc backticks ``(trong bash) như được đề cập trong câu trả lời của ire_and_curses.


3
gnu grep hỗ trợ cờ -Z để phân tách tên tệp bằng ký tự byte 0, khi được sử dụng cùng với cờ -0 thành xargs, có thể giải quyết vấn đề về các ký tự đặc biệt mà bạn đề cập
iruvar

@ChandraRavoori cảm ơn, tôi đã cập nhật câu trả lời.
peterph

7

Nếu tên tệp của bạn không chứa bất kỳ ký tự đặc biệt nào (khoảng trắng hoặc \[*?), hãy sử dụng lệnh thay thế :

mv `grep -lir 'string' ~/directory/*` destination/

Backticks không được chấp nhận; thay vào đó, hãy sử dụng $ (...) di động hơn, dễ đọc hơn và có thể xếp chồng lên nhau.
người dùng không xác định

1

Chỉ sử dụng các tính năng được chỉ định POSIX và không đưa ra giả định nào về tên tệp:

find ~/directory -type f -exec grep -qiF 'string' {} \; -exec mv {} /path/to/dest \;

Ghi chú:

Bạn đã nói "chuỗi" không phải là "mẫu", vì vậy -Ftùy chọn (tìm kiếm chuỗi cố định) grepcó vẻ phù hợp.

Nếu thư mục đích của bạn ở bất cứ đâu trong thư mục tìm kiếm của bạn, bạn có thể có một số điều kiện cuộc đua khó chịu.

Thông số kỹ thuật POSIX cho grep

Thông số kỹ thuật POSIX cho find


Đây có thể là giải pháp tốt nhất trên Macos / BSD
Ali

0

Sử dụng GNU song song :

grep -i -Z -r -l 'string' . | parallel 'mv {} destination/{}'

ht / @ lin-dong cho câu trả lời ban đầu của mình với xargs.


Sẽ thật tuyệt nếu bạn ghi có câu trả lời của @ lindong trong các bình luận từ hơn một năm trước.
roaima

0

-Assume rằng bạn có thư mục đích là 'bên ngoài' và cần di chuyển tất cả các tệp XLS, bạn có thể thử lệnh bên dưới

sudo mv find /var/log/ -type f -name "*.xls"/ bên ngoài /

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.