
Entorno de prueba:
- crear directorios desde
0
hasta9
y llenarlos con archivos desdea
hastaz
$ mkdir {0..9} && touch {0..9}/{a..z}
- Consecuencia de
find
:$ find -type f ./0/a ./0/b ... ./9/y ./9/z
¿Cómo puedo transformar la salida para que se vea así?
./0a
./0b
...
./9y
./9z
Respuesta1
Con el comando independiente de Perl rename
:
rename -n 's|/||' */*
Si todo se ve bien, elimine -n
y luego elimine los directorios vacíos restantes.
rmdir {0..9}
Respuesta2
Con herramientas POSIX,
find . -type f -exec sh -c 'for f; do dirn="${f%/*}"; mv -- "$f" "$dirn${f##*/}"; done' sh {} +
find
invoca un shell y ejecuta el bucle for para cada archivo.
dirn="${f%/*}"
obtiene el nombre del directorio principal excluyendo todo lo que está después (e incluyendo) la última barra diagonal en el nombre del archivo.${f##*/}
obtiene el nombre del archivo sin la ruta excluyendo todo lo que está antes (e incluyendo) la última barra diagonal en el nombre del archivo.
Esas dos construcciones de caparazón hacen lo mismo quedirname
ybasename
, por lo que una forma equivalente del comando es
find . -type f -exec sh -c 'for f; do mv -- "$f" "$(dirname "$f")$(basename "$f")"; done' sh {} +
, aunque éste debería ser más lento ya que necesita generar dos procesos adicionales para cada archivo.
Si no necesita descender a más de un directorio, como muestra su ejemplo, un simple bucle de shell lo hace:
for f in */*; do dirn="${f%/*}"; echo mv -- "$f" "$dirn${f##*/}"; done