
Ambiente de teste:
- crie diretórios de
0
para9
e preencha-os com arquivos dea
paraz
$ mkdir {0..9} && touch {0..9}/{a..z}
- Resultado de
find
:$ find -type f ./0/a ./0/b ... ./9/y ./9/z
Como posso transformar a saída para que fique assim:
./0a
./0b
...
./9y
./9z
Responder1
Com rename
o comando independente do Perl:
rename -n 's|/||' */*
Se tudo parecer bem, remova -n
e remova os diretórios vazios restantes.
rmdir {0..9}
Responder2
Com ferramentas POSIX,
find . -type f -exec sh -c 'for f; do dirn="${f%/*}"; mv -- "$f" "$dirn${f##*/}"; done' sh {} +
find
invoca um shell e executa o loop for para cada arquivo.
dirn="${f%/*}"
obtém o nome do diretório pai excluindo tudo o que vem depois (e incluindo) a última barra no nome do arquivo.${f##*/}
obtém o nome do arquivo sem o caminho, excluindo tudo o que está antes (e incluindo) a última barra no nome do arquivo.
Essas duas construções de shell fazem o mesmo quedirname
ebasename
, então uma forma equivalente do comando é
find . -type f -exec sh -c 'for f; do mv -- "$f" "$(dirname "$f")$(basename "$f")"; done' sh {} +
, embora este deva ser mais lento, pois precisa gerar dois processos extras para cada arquivo.
Se você não precisar descer para mais de um diretório, como mostra seu exemplo, um simples loop de shell fará isso:
for f in */*; do dirn="${f%/*}"; echo mv -- "$f" "$dirn${f##*/}"; done