Cómo mover todos los archivos dentro de las subcarpetas actuales aquí

8

También tengo 50 carpetas con algunas subcarpetas, con más de 1000 archivos de audio en total. Necesito eliminar todas las subcarpetas y poner todos los archivos en el nivel actual. Intenté mv */* ./pero se queja: la lista de argumentos es demasiado larga

Pedro González
fuente

Respuestas:

7

Supongo que la extensión de sus archivos de audio es .mp3

find <AudioFolderPath> -name '*.mp3' -exec mv -it <YourTargetFolder> {} +

Notas:

  • Reemplace .mp3con la extensión de sus archivos de audio

  • Reemplace <AudioParentFolderPath>con la carpeta principal que contiene sus subcarpetas.

  • Reemplace <YourTargetFolder>con la ruta de la carpeta en la que necesita colocar todos los archivos.

  • Si los archivos de arrastre de diferentes subcarpetas tienen el mismo nombre, solo se moverá uno.

editar: Como dijo Costas : "El -iinterruptor se vuelve mvinteractivo, se le solicitará antes de sobrescribir los archivos existentes"

Mahoma
fuente
¿'-t' le permite especificar primero el destino? (ya que no tengo esta opción en mi "mv" aquí, solo puedo suponer que al poner primero la carpeta de destino y luego la lista de archivos para mover allí ... pero si no, esto intentará encajar en todos en el último nombre de archivo, dando una advertencia) tpodría ser para "objetivo"?
Olivier Dulac
Sí, como dijiste, -tpermite especificar primero el destino. de la mvpágina del manual: -t, --target-directory=DIRECTORY move all SOURCE arguments into DIRECTORY
Muhammad
1
tenga en cuenta que esta es la opción de GNU mv, y no está disponible en todos los equipos (al menos en algunos entornos de producción). Proporciono una solución más portátil, pero la suya funciona bien para Linux
Olivier Dulac
sí @OlivierDulac, tienes razón, gracias por tu nota.
Muhammad
4
find . -type f -mindepth 2 -exec mv -t ./ {} +

Tenga en cuenta que ese comando sobrescribirá cualquier archivo con el mismo nombre. Puede usar esto para que se le solicite antes de sobrescribir:

find . -type f -mindepth 2 -exec mv -it ./ {} +

Explicación

  • -type f : solo encuentra archivos regulares.
  • -mindepth 2 : encuentra solo archivos en subdirectorios.
  • -exec mv -it ./ {}: el -execmedio "ejecuta este comando en cada archivo encontrado". El {}será reemplazado con los nombres de los archivos. El -iconmutador se vuelve mvinteractivo, se le preguntará antes de sobrescribir los archivos existentes y -testablecerá el directorio de destino ./.
  • +: junte los archivos (en una línea de argumento) tantos como el shell puede operar con el comando para invocar los tiempos mínimos del comando (no uno por uno sino uno a varios).

Con respecto a otras eliminaciones de carpetas vacías, puede usar la misma recepción:

find . -type d -empty -delete
Costas
fuente
1
-type fselecciona solo archivos sin formato, excluyendo enlaces simbólicos, canalizaciones con nombre y similares. Para mover todos los archivos que no sean directorios, puede hacerlo ! -type d.
jimmij
@jimmij Supongo que nadie almacena archivos de audio con el nombre de pipe u otra cosa. Si le preocupan los enlaces simbólicos, puede usar el -Lparámetro
Costas
1
-ies estándar, -tes solo GNU (nada que ver con Linux, que es solo un núcleo que se encuentra en algunos sistemas GNU y no GNU)
Stéphane Chazelas
Estoy de acuerdo con @ StéphaneChazelas: -tno existe en algunos sistemas (como un AIX no tan antiguo)
Olivier Dulac
@OlivierDulac Es casi imposible encontrar una decisión para satisfacer a todos, por lo que las diferentes variantes son bienvenidas. Nadie le prohíbe cambiar la cadena afind . -type f -mindepth 2 -exec mv {} ./ \;
Costas
2

Sí, ese es un límite en el tamaño acumulativo de argumentos y entorno pasados ​​a la execve()llamada del sistema al ejecutar un comando externo.

Con zsh, puedes usar su incorporado mven su lugar:

zmodload -F zsh/files +b:zf_mv
zf_mv ./*/* .

O use zargspara dividir la lista en fragmentos manejables:

autoload zargs
zargs -Ifiles ./*/* -- mv files .

Con ksh93:

command -x mv ./*/* .

Con GNU xargsy con GNU mvcon un shell donde printfestá integrado (la mayoría, mkshsiendo la excepción notable):

printf '%s\0' ./*/* | xargs -r0 mv -t .
Stéphane Chazelas
fuente
Tenga en cuenta que OP desea mover solo archivos, no directorios, por lo que debe ocuparse de eso. En zshcaso de que pueda poner algunos calificadores globales , por ejemplo, (.)o (^/)después del último *.
jimmij
0

Una solución bastante portátil podría ser:

buscar todos los archivos en cada subcarpeta y moverlos al directorio actual

find ./*/ -type f -print | xargs mv -i "{}" ./

Puede agregar un | egrep "\.au$|\.mp3$|\.ac3$"intermedio para asegurarse también de que los archivos que encontró son archivos con una extensión de audio (agregue tantas extensiones como sea necesario para cubrir todo tipo, solo proporciono 3 comunes)

Olivier Dulac
fuente
En su caso no hay necesidad de llamar finden absoluto. Solo lo suficiente echooprintf
Costas
@Costas: el OP menciona que hay tantos archivos que "*" no se puede expandir ... Aquí solo expando los 50 nombres de carpetas, y el resto es manejado por xargs
Olivier Dulac
Pero findno resuelva el problema, pero xargssí.
Costas