Mover archivos con find + xargs: target no es un directorio?

9

Cuando ejecuto el siguiente comando:

> mkdir some_dir
> find /foo/bar/ -name '*.csv' -print0 | xargs -0 mv {} some_dir

Recibo cientos de líneas que dicen:

mv: target `/foo/bar/XX.csv` is not a directory

¿Por qué? Pensé que los xargs se ejecutarían:

mv /foo/barXX.csv some_dir

por cada archivo que findencuentre. ¿Que esta pasando? Por cierto, esto es con zsh

Actualizar:

Actualización1:

Lo intenté:

find /foo/bar/ -name '*.csv' -print0 | xargs -0 mv {} -t some_dir

pero luego obtuve algunas líneas como:

mv: cannot stat `{}': No such file or directory

aunque creo que el comando está moviendo mis archivos correctamente.

Actualización2:

Parece que no necesito la -topción cuando lo uso mvsolo. Por ejemplo

> touch file1.txt
> touch file2.txt
> mkdir my_dir
> mv  file1.txt  file2.txt  my_dir

funciona bien. ¿Por qué necesito -tal usar xargs?

Amelio Vazquez-Reina
fuente

Respuestas:

14

Asumiendo que tiene GNU ( find, xargs, y mv), cambiar su comando para esto:

$ find /foot/bar/ -name '*.csv' -print0 | xargs -0 mv -t some_dir

extracto de la mvpágina man

   -t, --target-directory=DIRECTORY
          move all SOURCE arguments into DIRECTORY

Lo anterior xargs ...construirá el comando para que las llamadas a mover sean así:

 $ mv 1.csv 2.csv 3.csv ... -t some_dir

No necesito xargs

Puede omitir este enfoque simplemente findhaciendo todo el trabajo en sí mismo:

$ find /foot/bar/ -name '*.csv' -exec mv -t some_dir {} +

¿Por qué necesitas el mv -t ...?

Esto tiene que ver con la forma en que xargsestá construyendo el conjunto de archivos para pasar al comando que se ejecutará cada vez, (es decir mv ...).

Cuando ejecuta el mvcomando manualmente, usted controla cuántos nombres de archivo se le pasan y, por lo tanto, no necesita preocuparse por necesitarlo, -t my_dirya que siempre colocará el directorio de destino al final.

Referencias

slm
fuente
¡Gracias! Esto es muy útil. Sin embargo, estoy un poco confundido (ver mis actualizaciones)
Amelio Vazquez-Reina
1
El comando construido es mv -t some_dir 1.csv 2.csv 3.csv ...para que los argumentos del archivo sean los últimos. Ese es el error en la cuestión, con el fin de utilizar {}lo que tiene que pasar -I {}a xargs.
frostschutz
Gracias. Eso lo explica todo. ¿Qué pasa con la segunda pregunta que tuve en la Actualización 2? ¿Sabes por qué no necesito -tvarios archivos y un directorio con un archivo regular mv?
Amelio Vazquez-Reina
1
@ user815423426 - Lo actualizaré más tarde cuando tenga la oportunidad esta noche, sé por qué.
slm
@ user815423426 - Actualicé la pregunta, avíseme si tiene sentido wrt mv -t.
slm
1

También puede usar el comando ls en lugar del comando find:

ls /foot/bar/*.csv | xargs  mv -t some_dir
Luis Ángel Rodríguez
fuente