Bagaimana saya bisa menemukan file dan kemudian menggunakan xargs untuk memindahkannya?

28

Saya ingin menemukan beberapa file dan kemudian memindahkannya.

Saya dapat menemukan file dengan:

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

Saya mencoba memindahkannya ke ~/playdirektori saya dengan:

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

tapi itu tidak berhasil. Jelas saya membutuhkan dua argumen.
Tidak yakin apakah (atau bagaimana) untuk merujuk 'item terkini' xargs di perintah mv?

Michael Durrant
sumber
3
Mengapa? Anda dapat menggunakan placeholder dengan -I: find . | xargs -I'{}' mv '{}' ~/play/, tapi sebagai manusia mengatakan, bahwa “menyiratkan -xdan -L 1.” Jadi tidak ada keuntungan. Lebih baik tetap sederhana dan gunakanfind . -exec mv '{}' ~/play/ \;
manatwork
Silakan kirim sebagai jawaban untuk melihat suara jika Anda tidak keberatan :)
Michael Durrant
Hanya menanyakan alasanmu, karena aku merasa aku tidak mengerti. Jika Drav Sloan menambahkan catatan pada opsi yang tersirat, jawabannya akan sebaik yang saya bisa tulis. Jadi lebih baik pergi dengan itu.
manatwork
kemungkinan rangkap dari pola Find and move
slm
@manatwork Saya telah mengedit jawaban saya untuk mencerminkan poin-poin itu :)
Drav Sloan

Jawaban:

43

Lihatlah jawaban Stephane untuk metode terbaik, lihat jawaban saya untuk alasan tidak menggunakan solusi yang lebih jelas (dan alasan mengapa mereka bukan yang paling efisien).

Anda dapat menggunakan -Iopsi xargs:

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

Yang bekerja dalam mekanisme serupa dengan finddan {}. Saya juga akan mengutip -nameargumen Anda (karena file yang dimulai dengan xdalam direktori sekarang akan di-globed file dan diteruskan sebagai argumen untuk menemukan - yang tidak akan memberikan perilaku yang diharapkan!).

Namun, sebagaimana ditunjukkan oleh manatwork, sebagaimana dirinci dalam xargshalaman manual:

   -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.

Yang penting untuk dicatat adalah itu -L 1berarti hanya satu jalur output dari yang findakan diproses pada satu waktu. Ini artinya secara sintaksis sama dengan:

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

(yang menjalankan satu mvoperasi untuk setiap file).

Bahkan menggunakan -0argumen xargs GNU dan find -print0argumen tersebut menyebabkan perilaku yang persis sama -I- ini adalah clone()proses untuk setiap file 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) ---
.
.
.
Drav Sloan
sumber
Itu mengasumsikan nama file tidak mengandung karakter baris baru, kutipan tunggal, kutipan ganda atau backslash.
Stéphane Chazelas
17

Dengan alat GNU:

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

Opsi -t( --target) spesifik untuk GNU. -print0, -r, -0, Sementara non-standar dan berasal GNU juga ditemukan di beberapa implementasi lain seperti pada beberapa BSD.

POSIXly:

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

Keduanya menjalankan mvperintah sesedikit mungkin dan bekerja dengan karakter apa pun yang mungkin berisi nama file. GNU yang mungkin memiliki keunggulan yang findterus mencari file sambil mvmulai memindahkan batch pertama.

Waspadalah bahwa semua file dan direktori akan berakhir dalam satu direktori, waspadalah terhadap bentrokan jika beberapa file di direktori yang berbeda memiliki nama yang sama.

Stéphane Chazelas
sumber
Solusi ini jauh lebih baik kinerjanya, karena ia memanggil mvsekali untuk semua argumen (atau untuk semua -Latau -n, jika disediakan). Jika tidak, panggilan mvuntuk setiap file akan menjadi cepat (dan lambat).
r2evans
1

Mungkin perintah ini mungkin sekarang dan tidak kembali pada tahun 2013, tetapi ini berfungsi dengan baik untuk saya:

ls pattern* | xargs mv -t DESTINATION/

The -tmenempatkan kunci folder tujuan pertama, membebaskan mvperintah untuk memiliki semua argumen terakhir sebagai hanya file yang akan dipindahkan.

Nikhil VJ
sumber
1
ini adalah solusi paling sederhana yang bekerja untuk saya
ptetteh227
0

Anda dapat mencoba dengan perintah di bawah ini dan diuji dan bekerja dengan baik

find /tmp/ -ctime -1 -type f -name "x*" -exec mv -t ~/play/ {} \;
Praveen Kumar BS
sumber