Come posso trovare i file e quindi usare xargs per spostarli?


28

Voglio trovare alcuni file e poi spostarli.

Posso trovare il file con:

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

Ho provato a spostarli nella mia ~/playdirectory con:

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

ma non ha funzionato. Ovviamente mv ha bisogno di due argomenti.
Non sei sicuro se (o come) fare riferimento all'elemento corrente di xargs nel comando mv?


3
Perché? È possibile utilizzare segnaposto con -I: find . | xargs -I'{}' mv '{}' ~/play/, ma come uomo dice, che “implica -xe -L 1”. Così nessun guadagno. Meglio tenerlo semplice e usarefind . -exec mv '{}' ~/play/ \;
manatwork

Per favore, pubblica come risposta per vedere i voti se non ti dispiace :)
Michael Durrant,

Ho solo chiesto il tuo motivo, dato che avevo la sensazione di non aver capito il punto. Se Drav Sloan aggiunge la nota sulle opzioni implicite, la sua risposta sarà buona quanto la migliore che potrei scrivere. Quindi meglio andare con quello.
arte

possibile duplicato di Trova modello e sposta
slm

@manatwork Ho modificato la mia risposta in modo da riflettere quei punti più pazzi :)
Drav Sloan,

Risposte:


43

Guarda la risposta di Stephane per il metodo migliore, dai un'occhiata alla mia risposta per motivi di non usare le soluzioni più ovvie (e motivi per cui non sono le più efficienti).

Puoi usare l' -Iopzione di xargs:

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

Che funziona in un meccanismo simile a finde {}. Vorrei anche citare il tuo -nameargomento (perché un file che inizia xnella presente directory verrebbe archiviato in un file e passato come argomento da trovare - il che non darà il comportamento previsto!).

Tuttavia, come sottolineato da manatwork, come dettagliato nella xargspagina 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.

La cosa importante da notare è che -L 1significa che verrà elaborata una sola riga di output findalla volta. Ciò significa che sintatticamente è lo stesso di:

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

(che esegue una singola mvoperazione per ciascun file).

Anche usando l' -0argomento GNU xargs e l' find -print0argomento causa esattamente lo stesso comportamento di -I- questo è clone()un processo per ogni 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) ---
.
.
.

Ciò presuppone che i nomi dei file non contengano caratteri di nuova riga, virgolette singole, virgolette doppie o barra rovesciata.
Stéphane Chazelas,

17

Con gli strumenti GNU:

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

L' opzione -t( --target) è specifica per GNU. -print0, -r, -0, Mentre non standard e originari di GNU si trovano anche in alcune altre implementazioni, come su alcuni sistemi BSD.

POSIXly:

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

Entrambi eseguono il minor numero di mvcomandi necessario e funzionano indipendentemente dai caratteri che possono contenere i nomi dei file. Quello GNU potrebbe avere il vantaggio di findcontinuare a cercare file mentre mvinizia a spostare il primo batch.

Attenzione che tutti i file e le directory finiranno in una directory, attenzione agli scontri se più file in directory diverse hanno lo stesso nome.


Questa soluzione ha prestazioni molto migliori, poiché richiede mvuna volta per tutti gli argomenti (o per tutti -Lo -n, se forniti). Altrimenti, chiamare mvper ogni file diventerà vecchio (e lento) velocemente.
r2evans,

1

Forse questo comando è possibile ora e non era nel 2013, ma questo funziona perfettamente per me:

ls pattern* | xargs mv -t DESTINATION/

La -tchiave mette per prima la cartella di destinazione, liberando il mvcomando per avere tutti gli ultimi argomenti come solo i file da spostare.


1
questa è stata la soluzione più semplice che ha funzionato per me
ptetteh227

0

Puoi provare con il comando seguente e testato e ha funzionato bene

find /tmp/ -ctime -1 -type f -name "x*" -exec mv -t ~/play/ {} \;
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.