Estructura de carpetas aplanada

Estructura de carpetas aplanada

Tengo esta estructura de carpetas:

├── foo1
│   ├── bar1.txt
│   └── bar2.txt
├── foo2
│   ├── bar3.txt
│   └── bar4 with a space.txt
└── foo3
    └── qux1
        ├── bar5.txt
        └── bar6.txt

que me gustaría aplanar en esto, con un guión bajo entre cada nivel de carpeta:

├── foo1_bar1.txt
├── foo1_bar2.txt
├── foo2_bar3.txt
├── foo2_bar4 with a space.txt
├── foo3_qux1.bar6.txt
└── foo3_qux1_bar5.txt

He mirado a mi alrededor y no he encontrado ninguna solución que funcione, creo que principalmente porque mi problema tiene dos particularidades: puede haber más de un nivel de carpeta dentro del nivel raíz y también porque algunos archivos pueden tener espacios.

¿Alguna idea de cómo lograr esto en bash? ¡Gracias!

Editar: Al ejecutar la respuesta propuesta por Glen Jackman, obtengo esto:

ingrese la descripción de la imagen aquí

Hay dos guiones bajos para la carpeta de primer nivel. ¿Alguna idea de cómo evitar esto o simplemente cambiarle el nombre para que sea solo un guión bajo? Gracias.

Respuesta1

find */ -type f -exec bash -c 'file=${1#./}; echo mv "$file" "${file//\//_}"' _ '{}' \;

elimínelo echosi está satisfecho de que está funcionando. No se preocupe si los comandos repetidos no muestran comillas, el script manejará los archivos con espacios correctamente.

Si desea eliminar los subdirectorios ahora vacíos:

find */ -depth -type d -exec echo rmdir '{}' \; 

Respuesta2

Usando el cambio de nombre de Perl:

find . -depth -type f -exec rename 's@(?<!\.)/@_@g' -- {} \;

PRODUCCIÓN

$ find -type f
./foo2_bar4 whit a space.txt
./foo3_qux1_bar6.txt
./foo2_bar3.txt
./foo3_qux1_bar5.txt
./foo1_bar2.txt
./foo1_bar1.txt

NOTA

  • Uso unmirada negativa detrás (?<!\.)no tocar el primero./
  • Mantengo los directorios vacíos, siéntete libre de:

    find . -depth -type d -exec rm {} \;

advertenciaHay otras herramientas con el mismo nombre que pueden o no ser capaces de hacer esto, así que tenga cuidado.

Si ejecuta el siguiente comando ( GNU)

$ file "$(readlink -f "$(type -p rename)")"

y tienes un resultado como

.../rename: Perl script, ASCII text executable

y que no contenga:

ELF

entonces esta parece ser la herramienta adecuada =)

De lo contrario, para convertirlo en el valor predeterminado (generalmente ya es el caso) en Debianun derivado como Ubuntu:

$ sudo update-alternatives --set rename /path/to/rename

(reemplace /path/to/renamela ruta de su perl's renamecomando.


Si no tiene este comando, busque en su administrador de paquetes para instalarlo ohazlo manualmente


Por último, pero no menos importante, esta herramienta fue escrita originalmente por Larry Wall, el padre de Perl.

Respuesta3

conpax...

pax -Xrwls '|/|_|g' */ "$PWD"

Eso creará un vínculo físico en el directorio actual a todos los archivos en sus directorios secundarios con un _sustituto de /. Luego puede inspeccionar los resultados y eliminar todos los directorios secundarios con...

rm -rf */

...una vez que hayas verificado los resultados son de tu agrado.

Respuesta4

Puedes probar con el siguiente comando.

$ find -type f -exec bash -c 'mv $0 $(echo $0|sed "s/\//_/2")' {} \;

El comando anterior moverá los archivos y el directorio permanecerá y podrá eliminarse más adelante.

$ ls
foo1_bar1.txt  foo1_bar2.txt  foo2_bar3.txt  foo2_bar4.txt  foo3_bar5.txt  foo3_bar6.txt

información relacionada