Acoplar la jerarquía de directorios preservando los nombres de directorio en un nuevo nombre de directorio

7

Básicamente quiero ir de esto:

.
├── Alan Walker
│   ├── Different World
│   │   ├── 01 Intro.mp3
│   │   ├── 02 Lost Control.mp3
│   │   └── cover.jpg
│   └── Same World
│       ├── 01 Intro.mp3
│       └── 02 Found Control.mp3
├── Aurora
│   └── Infections Of A Different Kind Step 1
│       ├── 01 Queendom.lrc
│       ├── 02 Forgotten Love.lrc
│       └── 03 Gentle Earthquakes.mp3
└── Guns N' Roses
    └── Use Your Illusion I
        ├── 01 Right Next Door To Hell.lrc
        ├── 01 Right Next Door To Hell.mp3
        ├── 02 Dust N' Bones.lrc
        └── 02 Dust N' Bones.mp3

a esto:

.
├── Alan Walker - Different World
│   ├── 01 Intro.mp3
│   ├── 02 Lost Control.mp3
│   └── cover.jpg
├── Alan Walker - Same World
│   ├── 01 Intro.mp3
│   └── 02 Found Control.mp3
├── Aurora - Infections Of A Different Kind Step 1
│   ├── 01 Queendom.lrc
│   ├── 02 Forgotten Love.lrc
│   └── 03 Gentle Earthquakes.mp3
└── Guns N' Roses - Use Your Illusion I
    ├── 01 Right Next Door To Hell.lrc
    ├── 01 Right Next Door To Hell.mp3
    ├── 02 Dust N' Bones.lrc
    └── 02 Dust N' Bones.mp3

Ninguna de las soluciones existentes que pude encontrar incluía renombrar el directorio en sí. Sería genial poder hacer esto con zmv, pero no puedo entender cómo hacerlo.

aksh1618
fuente
2
No es una solución completa, por lo que no es una respuesta: easytagpuede dejar de hacer esto, pero sólo para archivos de audio - No creo que se moverá cubiertas, etc.
RVs
2
¿Podría haber más de un álbum para un artista específico dentro de un directorio de artistas? ¿La estructura siempre tiene tres niveles de profundidad?
nohillside
1
@nohillside Sí, puede haber más de un álbum para un artista. Y sí, la estructura siempre tiene tres niveles de profundidad.
aksh1618

Respuestas:

9

Zsh

No probado:

zmv -Q '(*)/(*)(/)' '$1 - $2'
rmdir -- *(/^F)

La segunda línea elimina todos los directorios vacíos, incluso aquellos que no tenían un archivo antes. Es posible solucionar esto con un mvcontenedor personalizado que registra desde qué directorios mueve las cosas.

Tenga en cuenta que esto atraviesa enlaces simbólicos a directorios en el directorio actual.

Utilidad de cambio de nombre de Linux

No probado

rename / ' - ' */*/
rmdir -- */ 2>/dev/null

Tenga en cuenta que esto atraviesa enlaces simbólicos a directorios en el directorio actual y en sus subdirectorios. La segunda línea elimina todos los directorios vacíos, incluso aquellos que no tenían un archivo antes.

Script de cambio de nombre de Perl

No probado

prename 's~/~ - ~' */*/
rmdir -- */ 2>/dev/null

Tenga en cuenta que esto atraviesa enlaces simbólicos a directorios en el directorio actual y en sus subdirectorios. La segunda línea elimina todos los directorios vacíos, incluso aquellos que no tenían un archivo antes.

Aquí hay un enfoque más complejo que solo elimina los directorios de los que renombró algo. De nuevo, no probado.

prename 's~([^/]+)/~$1 - ~ and ++$d{$1}; END {map {rmdir} keys %d}' */*/
Gilles 'SO- deja de ser malvado'
fuente
12

¿Algo así quizás?

#!/bin/sh

for topdir in */; do
    topdir_name=$( basename "$topdir" )

    for subdir in "$topdir"/*/; do
        subdir_name=$( basename "$subdir" )

        newdir="$topdir_name - $subdir_name"
        if mkdir "$newdir"; then
            mv "$subdir"/* "$newdir"
            rmdir "$subdir"
        fi
    done

    rmdir "$topdir"
done

Esto pasa por todos los directorios de nivel superior en el directorio actual (los nombres de las bandas). Para cada directorio, pasa por sus subdirectorios (los nombres de los álbumes). Para cada par de nombre de banda y nombre de álbum, se crea un nuevo directorio y los archivos del subdirectorio se mueven a él. Los subdirectorios del álbum se eliminan cuando se han procesado, al igual que los directorios de nivel superior de la banda original.

Las rmdirllamadas fallarán si algún directorio contiene nombres de archivo ocultos o si alguno de los nuevos directorios no se pudo crear.

Este es un código totalmente no probado. Ejecútelo en una copia de seguridad de sus archivos.

Kusalananda
fuente
Quiero decir, sí, algo así funcionaría, pero estoy buscando una solución de una o dos líneas, para ejecutar fácilmente desde la terminal. Algunos encuentran / sed / zmv magic :)
aksh1618
10
Ponga ot en un script, y -boom- se convierte en una línea.
Hans-Martin Mosner
4

Estratégicamente, en lugar de mover archivos, ¿ha considerado dejar la estructura actual en su lugar y crear enlaces para la nueva estructura que desea?

Tácticamente, un patrón que hará el trabajo es el siguiente:

find . -mindepth 2 -maxdepth 2 -type d -print0 | xargs -0n1 bash -c \
  'b=$(basename "$(dirname "$1")"); a=$(basename "$1"); echo ln -s "$1" "$b-$a"' {}
  • findubica todos los directorios exactamente a dos niveles de profundidad del directorio de trabajo actual, que debería ser el directorio que contiene las bandas: por lo tanto, dos niveles de profundidad son los nombres de los álbumes debajo de los nombres de las bandas. 1
  • xargs consume cada ruta que contiene un álbum y llama a la secuencia de comandos bash en línea.
  • bash -c '...'toma la ruta del álbum como primer argumento, dividiendo esa ruta en dos partes: la banda ( $b) y el álbum ( $a). Finalmente, el script vuelve a ensamblar los nombres en el formato deseado y vincula el nuevo nombre del directorio al directorio original.

Tenga en cuenta que, en este ejemplo, los enlaces se crearían en el mismo directorio desde el que comienza, que también es donde están los nombres de las bandas.

Podrías y deberías ajustar la lnestrategia anterior para que coincida con tu intención. mvcon los caminos correctos si físicamente desea reorganizar, o lnsi desea crear una "vista" conveniente a través de los medios. Las partes importantes dentro del script bash son:

  • $bEl nombre de la banda. Siempre hay que indicar que: "$b".
  • $aEl nombre del álbum. Siempre hay que indicar que: "$a".
  • $1La ruta física al directorio del álbum. Siempre hay que indicar que: "$1".

1 Creo que m{ax,in}depthson compatibles con GNU y algunos BSD find, pero no con POSIX: en cuyo caso, confíe en */*gimnasia de shell o similar.

obispo
fuente
1
Me gusta esta respuesta ... también podría hacer enlaces duros, luego eliminar la estructura de carpetas anterior cuando esté satisfecho
Thomas Zwaagstra
@ThomasZwaagstra Eso no es diferente a mover los archivos
Darkhogg
1
@Darkhogg ¡Exactamente! OP estaba buscando un 1-liner para mover los archivos. El uso de enlaces duros con esta solución casi lograría eso, excepto que tendría una etapa intermedia de "vista previa" antes de eliminar los archivos originales
Thomas Zwaagstra