Estoy buscando archivos cuyo nombre contenga AAA
en su ruta utilizando el siguiente comando:
find path_A -name "*AAA*"
Dada la salida mostrada por el comando anterior, quiero mover esos archivos a otra ruta, digamos ruta_B
. En lugar de mover esos archivos uno por uno, ¿puedo optimizar el comando moviendo esos archivos justo después del comando find?
Con GNU mv:
find path_A -name '*AAA*' -exec mv -t path_B {} +
Esto utilizará la opción exec
de find's que reemplaza el {}
con cada resultado de find en turno y ejecuta el comando que le des. Como se explica en man find
:
-exec command ;
Execute command; true if 0 status is returned. All following
arguments to find are taken to be arguments to the command until
an argument consisting of `;' is encountered.
En este caso, estamos utilizando la versión +
de -exec
para que se ejecuten el menor número posible de operaciones mv
:
-exec command {} +
This variant of the -exec action runs the specified command on
the selected files, but the command line is built by appending
each selected file name at the end; the total number of invoca‐
tions of the command will be much less than the number of
matched files. The command line is built in much the same way
that xargs builds its command lines. Only one instance of `{}'
is allowed within the command. The command is executed in the
starting directory.
También se puede hacer algo como lo que se indica a continuación.
find path_A -name "*AAA*" -print0 | xargs -0 -I {} mv {} path_B
Donde,
-0
Si hay espacios o caracteres en blanco (incluyendo nuevas líneas) muchos comandos no funcionarán. Esta opción se encarga de los nombres de archivo con
espacio en blanco.-I
Reemplaza las ocurrencias de replace-str en los argumentos iniciales con nombres leídos de la entrada estándar. Además, los espacios en blanco no entrecomillados no
terminan los elementos de entrada; en su lugar, el separador es el carácter
de la línea nueva.**Pruebas
He creado dos directorios como sourcedir
y destdir
. Ahora, he creado un montón de archivos dentro de sourcedir
como file1.bak
, file2.bak
y file3 con espacios.bak
.
Ahora, he ejecutado el comando como,
find . -name "*.bak" -print0 | xargs -0 -I {} mv {} /destdir/
Ahora, dentro del destdir
, cuando hago ls
, pude ver que los archivos se han movido de sourcedir
a destdir
.
Referencias
http://www.cyberciti.biz/faq/linux-unix-bsd-xargs-construct-argument-lists-utility/
El exec
es la mejor manera de hacerlo. Si, por alguna razón, esto no es una opción, también puede leer los resultados en un bucle:
find path_A -name "*AAA*" -print0 |
while IFS= read -r -d $'\0' file; do mv "$file" path_B; done
Esa'es la forma segura, puede lidiar con nombres de archivos que contengan espacios, nuevas líneas u otros caracteres extraños. Una forma más sencilla, pero que fracasa a menos que sus nombres de archivo consistan sólo en caracteres alfanuméricos simples, es
mv $(find path_A -name "*AAA*") path_B
Pero utiliza el bucle while.