![Estructura de carpetas aplanada](https://rvso.com/image/36020/Estructura%20de%20carpetas%20aplanada.png)
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:
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 echo
si 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 {} \;
Hay 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 Debian
un derivado como Ubuntu
:
$ sudo update-alternatives --set rename /path/to/rename
(reemplace /path/to/rename
la ruta de su perl's rename
comando.
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