Mueva todos los archivos con una cierta extensión desde múltiples subdirectorios a un directorio

43

Tengo un montón de archivos .zip en varios directorios:

Fol1/Fol2
Fol3
Fol4/Fol5

¿Cómo los movería a una carpeta base común?

InquilineKea
fuente
¿Quieres mantener la estructura del directorio? ¿Desea mover los directorios o solo los archivos zip?
jordanm
Solo quiero mover los archivos zip. Realmente no me importan los directorios: se pueden dejar solos o eliminar.
InquilineKea

Respuestas:

55

Vaya al directorio de nivel superior del árbol que contiene los archivos zip ( cd …), luego ejecute

mv **/*.zip /path/to/single/target/directory

Esto funciona fuera de la caja en zsh. Si su shell es bash, shopt -s globstarprimero deberá ejecutarlo (puede y debe poner este comando en su ~/.bashrc). Si su shell es ksh, set -o globstarprimero deberá ejecutarlo (ponerlo en su ~/.kshrc).

Alternativamente, use find, que funciona en todas partes sin una preparación especial, pero es más complicado:

find . -name '*.zip' -exec mv {} /path/to/single/target/directory \;

Si desea eliminar directorios vacíos después, en zsh:

rmdir **/*(/^Fod)

En bash o ksh:

rmdir **/*/

y repita siempre que haya directorios vacíos para eliminar. Alternativamente, en cualquier caparazón

find . -depth -type d -empty -exec rmdir {} \;
Gilles 'SO- deja de ser malvado'
fuente
El primer findcomando anterior funcionó en bash, pero tuvo que cambiar a find . -nameetc. para que funcione.
JeffThompson
1
@Jeff .está implícito para GNU find pero no para otros, lo he agregado explícitamente.
Gilles 'SO- deja de ser malvado'
13

Si solo desea mover los .ziparchivos, puede hacer algo como

mkdir ./zipfiles
find . -name "*.zip" -exec mv "{}" ./zipfiles \;
Bernhard
fuente
3

Si usa bash versión 4 o superior o zsh , también puede usar globbing recursivo:

mv **/*.zip /path/to/move/zip/files/to

Esto moverá SOLAMENTE los archivos y no sus rutas relativas, por lo que pueden ocurrir colisiones.

SuperMagic
fuente
¿Qué quieres decir con caminos relativos?
Kunok
2

Este es seguro al mover datos y sin errores, lo que es compatible con la mayoría de las distribuciones independientemente de las versiones. Este comando escaneará subdirectorios y luego se moverá o copiará a su nuevo directorio de destino.

find . -name *.flac -exec mv '{}' "./flac/" ";"
  • Ejecute este comando en el directorio principal que contiene subdirectorios con los archivos que desea mover.
  • Donde puede cambiar *.flaca algo como *.zipen su caso. O *.docsimplemente cualquier extensión funciona.
  • y mves el comando para mover archivos, o puede usar cppara copiar datos en lugar de moverlos.
  • ./flac/es el directorio de destino al que quiero mover todos los archivos FLAC. También puedes darle un camino completo como/home/myid/flac/

Ejemplo completo. (en este caso, hay muchos subdirectorios con el nombre del artista de música en /home/myid/Music/y luego los archivos FLAC están en diferentes niveles de subdirectorios. Dado que no necesito carpetas de artistas pero quiero tener todos los archivos FLAC en un directorio en/home/myid/Music/flac/

cd /home/myid/Music
mkdir flac
find . -name *.flac -exec mv '{}' "./flac/" ";"
cd flac
ls

Luego mostrará todos los archivos FLAC.

Seandex
fuente
¿qué ;hacer?
Francesco Boi
@FrancescoBoi, asegúrese de esperar hasta que el comando bash en la misma línea termine su trabajo. y luego pasar a la siguiente línea de comandos bash. Esto es útil para comandos que contienen scripts como .pl o python porque bash simplemente lo ejecutará y luego saltará a la siguiente línea, así que para estar seguro, lo uso; después de los comandos que lleva tiempo o script, en caso de que bash lo omita.
Seandex
0

Como un hack bash, podrías usar el poder de tar:

(cd origin/;find . -exec file --mime-type "{}" \;|grep "application/zip"|cut -d ':' -f 1|xargs tar cf -)|(cd target/; tar xf -) && rm -fr origin/

Esto tiene la ventaja de que no depende de las extensiones de archivo, ya que utiliza el filecomando para elegir los archivos a mover y conserva la estructura del directorio, pero no funciona con rutas que contienen espacios.

La final rmestá ahí solo para eliminar los archivos originales (porque @InquilineKea dice que no le importa la carpeta original en el comentario).

Por supuesto, esto es particularmente adecuado si las carpetas de origen / destino / están en discos diferentes. De lo contrario, las otras soluciones propuestas son más eficientes (incluso si se basan en convenciones de nomenclatura, en lugar del filecontenido).

Giacomo Tesio
fuente
0

Suponiendo que tiene las versiones GNU de find y mv, lo siguiente será más eficiente que las respuestas basadas en find existentes:

find . -name '*.zip' -exec mv --target-directory='/path/to/outputdir' '{}' +

Usar un +al final de find -exec significa que se pasará una lista de archivos al comando mv, en lugar de ejecutar un comando mv por archivo encontrado. Sin embargo, una limitación de esto es que solo puede colocar el '{}' al final del comando, lo que requiere el uso de la opción mv --target-directory, y que yo sepa, eso es un GNU-ismo.

maldad
fuente