![Achatando estrutura de pastas](https://rvso.com/image/36020/Achatando%20estrutura%20de%20pastas.png)
Eu tenho essa estrutura de pastas:
├── foo1
│ ├── bar1.txt
│ └── bar2.txt
├── foo2
│ ├── bar3.txt
│ └── bar4 with a space.txt
└── foo3
└── qux1
├── bar5.txt
└── bar6.txt
que eu gostaria de nivelar, com um sublinhado entre cada nível de pasta:
├── foo1_bar1.txt
├── foo1_bar2.txt
├── foo2_bar3.txt
├── foo2_bar4 with a space.txt
├── foo3_qux1.bar6.txt
└── foo3_qux1_bar5.txt
Procurei e não encontrei nenhuma solução que funcionasse, principalmente porque meu problema tem duas particularidades: pode haver mais de um nível de pasta dentro da raiz e também porque alguns arquivos podem ter espaços.
Alguma idéia de como fazer isso no bash? Obrigado!
Editar: Executando a resposta proposta de gleen jackman, recebo o seguinte:
Existem dois sublinhados para a pasta de primeiro nível. Alguma idéia de como evitar isso ou apenas renomeá-lo para que seja apenas um sublinhado? Obrigado.
Responder1
find */ -type f -exec bash -c 'file=${1#./}; echo mv "$file" "${file//\//_}"' _ '{}' \;
remova echo
se estiver satisfeito com o funcionamento. Não se preocupe, pois os comandos echo'ed não mostram aspas, o script irá lidar com arquivos com espaços corretamente.
Se você deseja remover os subdiretórios agora vazios:
find */ -depth -type d -exec echo rmdir '{}' \;
Responder2
Usando a renomeação do Perl:
find . -depth -type f -exec rename 's@(?<!\.)/@_@g' -- {} \;
SAÍDA
$ 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
OBSERVAÇÃO
- Eu uso umolhar negativo para trás
(?<!\.)
não tocar no primeiro./
Eu mantenho os diretórios vazios, fique à vontade para:
find . -depth -type d -exec rm {} \;
Existem outras ferramentas com o mesmo nome que podem ou não fazer isso, então tome cuidado.
Se você executar o seguinte comando ( GNU
)
$ file "$(readlink -f "$(type -p rename)")"
e você tem um resultado como
.../rename: Perl script, ASCII text executable
e não contendo:
ELF
então esta parece ser a ferramenta certa =)
Caso contrário, para torná-lo o padrão (geralmente já é o caso) em uma Debian
derivada como Ubuntu
:
$ sudo update-alternatives --set rename /path/to/rename
(substitua /path/to/rename
pelo caminho do seu perl's rename
comando.
Se você não possui este comando, procure em seu gerenciador de pacotes para instalá-lo oufaça isso manualmente
Por último, mas não menos importante, esta ferramenta foi originalmente escrita por Larry Wall, o pai do Perl.
Responder3
compax
...
pax -Xrwls '|/|_|g' */ "$PWD"
Isso criará um hardlink no diretório atual para todos os arquivos em seus diretórios filhos, substituído _
por /
. Você pode então inspecionar os resultados e remover todos os diretórios filhos com...
rm -rf */
...depois de verificar se os resultados estão do seu agrado.
Responder4
Você pode tentar com o comando abaixo.
$ find -type f -exec bash -c 'mv $0 $(echo $0|sed "s/\//_/2")' {} \;
O comando acima moverá os arquivos e o diretório permanecerá, que poderá ser removido posteriormente.
$ ls
foo1_bar1.txt foo1_bar2.txt foo2_bar3.txt foo2_bar4.txt foo3_bar5.txt foo3_bar6.txt