Copie todos los archivos con una determinada extensión de todos los subdirectorios

112

En unix, quiero copiar todos los archivos con una determinada extensión (todos los archivos de Excel) de todos los subdirectorios a otro directorio. Tengo el siguiente comando:

cp --parents `find -name \*.xls*` /target_directory/

Los problemas con este comando son:

  • También copia la estructura del directorio, y solo quiero los archivos (por lo que todos los archivos deberían terminar en / target_directory /)

  • No copia archivos con espacios en los nombres de archivo (que son bastantes)

¿Alguna solución para estos problemas?

Abdel
fuente
¿Qué hay de find... exec mv?
fedorqui 'SO deja de dañar'

Respuestas:

174

--parents está copiando la estructura del directorio, por lo que debería deshacerse de eso.

La forma en que ha escrito esto, se findejecuta y la salida se coloca en la línea de comando de manera que cpno se puede distinguir entre los espacios que separan los nombres de archivo y los espacios dentro del nombre de archivo. Es mejor hacer algo como

$ find . -name \*.xls -exec cp {} newDir \;

en el que cpse ejecuta para cada nombre de archivo que findencuentra, y pasa el nombre de archivo correctamente. Aquí hay más información sobre esta técnica.

En lugar de todo lo anterior, puede usar zsh y simplemente escribir

$ cp **/*.xls target_directory

zsh puede expandir comodines para incluir subdirectorios y hace que este tipo de cosas sea muy fácil.

Brian Agnew
fuente
2
Si. 'bin it' significa tirarlo a la basura. Ahora modificado :-)
Brian Agnew
13
Bash4.0+ y ksh93también es compatible **. Para bash, use shopt -s globstarpara habilitarlo. Para ksh, es set -Go set -o globstar.
pynexj
2
@Daryl - He completado más. Pero la respuesta ya estaba marcada como 'aceptada', nota
Brian Agnew
5
Ese ejecutivo es técnicamente menos eficiente que pasar a xargs, que lo hará todo en la menor cantidad posible de llamadas de cp: find . -name '*.xls' -print0 | xargs -0 cp -t destdir
Taywee
2
@BrianAgnew Oh, estoy seguro, es bueno tener información adicional en los comentarios para los googlers descarriados.
Taywee
37

De todo lo anterior, se me ocurrió esta versión. Esta versión también me funciona en la terminal de recuperación de mac.

find ./ -name '*.xsl' -exec cp -prv '{}' '/path/to/targetDir/' ';'

Buscará en el directorio actual y de forma recursiva en todos los subdirectorios los archivos con la extensión xsl. Los copiará todos al directorio de destino.

Las banderas de cp son:

  • p - conserva los atributos del archivo
  • r - recursivo
  • v - detallado (muestra lo que se está copiando)
guya
fuente
1
Esto es lo mismo que tuve que hacer cuando SSH en Bluehost.
Plummer
4
NO conserva subdirecciones.
b005t3r
3
@ b005t3r que es por diseño, no se supone que lo haga. Esa fue toda la intención de la pregunta del OP. Quería que todos los archivos de los subdirectorios se copiaran en un directorio sin subdirectorios
Madivad
2
¿Hay alguna forma de modificar esto para preservar los subdirectorios?
Matthew Dean
8

Tuve un problema similar. Lo resolví usando:

find dir_name '*.mp3' -exec cp -vuni '{}' "../dest_dir" ";"

El '{}'y ";"ejecuta la copia de cada archivo.

stingMantis
fuente
3

También tuve que hacer esto yo mismo. Lo hice a través del argumento --parents para cp:

find SOURCEPATH -name filename*.txt -exec cp --parents {} DESTPATH \;
Ese tipo
fuente
1
find [SOURCEPATH] -type f -name '[PATTERN]' | 
    while read P; do cp --parents "$P" [DEST]; done

puede eliminar los --parents, pero existe el riesgo de colisión si varios archivos tienen el mismo nombre.

Camión
fuente