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?
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?
Câu trả lời:
Như mọi khi, hãy cẩn thận grep -r
. -r
khô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.
xargs
thoá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 đó.
Sử dụng xargs
trong buổi hòa nhạc với mv
cú 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
có -Z
/ --null
tùy chọn để kết thúc tên tệp NUL.
Một thay thế cho cú pháp thứ ba cho mv
việc sử dụng xargs
vớ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.
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/
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 -F
tùy chọn (tìm kiếm chuỗi cố định) grep
có 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.
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.
-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 /
grep -i -Z -r -l 'string' . | xargs -I{} mv {} ./folder_name