Làm thế nào tôi có thể tìm thấy các tập tin và sau đó sử dụng xargs để di chuyển chúng?


28

Tôi muốn tìm một số tập tin và sau đó di chuyển chúng.

Tôi có thể tìm thấy tập tin với:

$ find /tmp/ -ctime -1 -name x*

Tôi đã cố gắng chuyển chúng vào ~/playthư mục của tôi với:

$ find /tmp/ -ctime -1 -name x* | xargs mv ~/play/

nhưng điều đó đã không làm việc. Rõ ràng mv cần hai đối số.
Không chắc chắn nếu (hoặc làm thế nào) để tham chiếu 'mục hiện tại' của xargs trong lệnh mv?


3
Tại sao? Bạn có thể sử dụng trình giữ chỗ với -I: find . | xargs -I'{}' mv '{}' ~/play/, nhưng như người đàn ông nói, đó là Implies -x-L 1. Vì vậy, không có lợi. Tốt hơn là giữ cho nó đơn giản và sử dụngfind . -exec mv '{}' ~/play/ \;
manatwork

Vui lòng gửi dưới dạng câu trả lời để xem phiếu bầu nếu bạn không phiền :)
Michael Durrant

Chỉ cần hỏi lý do của bạn, vì tôi có cảm giác tôi không có điểm. Nếu Drav Sloan thêm ghi chú vào các tùy chọn ngụ ý, câu trả lời của anh ta sẽ tốt nhất có thể như tôi viết. Vì vậy, tốt hơn đi với điều đó.
manatwork

có thể trùng lặp mô hình Tìm và di chuyển
slm

@manatwork Tôi đã chỉnh sửa câu trả lời của mình để phản ánh những điểm đó :)
Drav Sloan

Câu trả lời:


43

Hãy xem câu trả lời của Stephane để biết phương pháp tốt nhất, hãy xem câu trả lời của tôi để biết lý do không sử dụng các giải pháp rõ ràng hơn (và lý do tại sao chúng không hiệu quả nhất).

Bạn có thể sử dụng -Itùy chọn xargs:

find /tmp/ -ctime -1 -name "x*" | xargs -I '{}' mv '{}' ~/play/

Mà hoạt động trong một cơ chế tương tự find{}. Tôi cũng sẽ trích dẫn -nameđối số của bạn (vì một tệp bắt đầu xtrong thư mục hiện tại sẽ bị lấp đầy tệp và được chuyển qua làm đối số cần tìm - sẽ không đưa ra hành vi mong đợi!).

Tuy nhiên, như được chỉ ra bởi manatwork, như chi tiết trong xargstrang man:

   -I replace-str
          Replace occurrences of replace-str in the initial-arguments with
          names read from standard input.  Also, unquoted  blanks  do  not
          terminate  input  items;  instead  the  separator is the newline
          character.  Implies -x and -L 1.

Điều quan trọng cần lưu ý là điều đó -L 1có nghĩa là chỉ một dòng đầu ra từ findsẽ được xử lý tại một thời điểm. Điều này có nghĩa là về mặt cú pháp giống như:

find /tmp/ -ctime -1 -name "x*" -exec mv '{}' ~/play/

(thực thi một mvthao tác duy nhất cho mỗi tệp).

Ngay cả khi sử dụng -0đối số GNU xargs và find -print0đối số gây ra chính xác cùng một hành vi của -I- đây là clone()một quy trình cho mỗi tệp mv:

find . -name "x*" -print0 | strace xargs -0 -I '{}' mv '{}' /tmp/other

.
.
read(0, "./foobar1/xorgslsala11\0./foobar1"..., 4096) = 870
mmap(NULL, 135168, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) =     0x7fbb82fad000
open("/usr/lib/x86_64-linux-gnu/gconv/gconv-modules.cache", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=26066, ...}) = 0
mmap(NULL, 26066, PROT_READ, MAP_SHARED, 3, 0) = 0x7fbb82fa6000
close(3)                                = 0
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD,         child_tidptr=0x7fbb835af9d0) = 661
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 661
--- SIGCHLD (Child exited) @ 0 (0) ---
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD,         child_tidptr=0x7fbb835af9d0) = 662
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 662
--- SIGCHLD (Child exited) @ 0 (0) ---
.
.
.

Giả sử tên tệp không chứa dòng mới, trích dẫn đơn, trích dẫn kép hoặc ký tự dấu gạch chéo ngược.
Stéphane Chazelas

17

Với các công cụ GNU:

find /tmp/ -ctime -1 -name 'x*' -print0 |
  xargs -r0 mv -t ~/play/

Các -t( --target) lựa chọn là GNU cụ thể. -print0, -r, -0, Trong khi phi tiêu chuẩn và có nguồn gốc trong GNU cũng được tìm thấy trong một số hiện thực khác như trên một số BSDs.

POSIXly:

find /tmp/ -ctime -1 -name 'x*' -exec sh -c '
  exec mv "$@" ~/play/' sh {} +

Cả hai đều chạy một số mvlệnh khi cần thiết và hoạt động bất kỳ ký tự nào mà tên tệp có thể chứa. GNU có thể có lợi thế là findtiếp tục tìm kiếm các tệp trong khi mvbắt đầu di chuyển lô đầu tiên.

Lưu ý rằng tất cả các tệp và thư mục sẽ kết thúc trong một thư mục, hãy cẩn thận với các xung đột nếu một số tệp trong các thư mục khác nhau có cùng tên.


Giải pháp này hoạt động tốt hơn nhiều, vì nó gọi mvmột lần cho tất cả các đối số (hoặc cho tất cả -Lhoặc -n, nếu được cung cấp). Nếu không, gọi mvcho mỗi tệp sẽ nhanh chóng (và chậm).
r2evans

1

Có lẽ lệnh này hiện có thể và không trở lại vào năm 2013, nhưng điều này hoạt động hoàn hảo với tôi:

ls pattern* | xargs mv -t DESTINATION/

Các -tputs chìa khóa thư mục đích đầu tiên, giải phóng mvlệnh để có tất cả các đối số cuối cùng là chỉ các tập tin được di chuyển.


1
đây là giải pháp đơn giản nhất có hiệu quả với tôi
ptetteh227

0

Bạn có thể thử với lệnh dưới đây và thử nghiệm và nó hoạt động tốt

find /tmp/ -ctime -1 -type f -name "x*" -exec mv -t ~/play/ {} \;
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.