Estrutura de pastas de nivelamento

8

Eu tenho esta 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 achatar, 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

Eu olhei em volta 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 do raiz e também porque alguns arquivos podem ter espaços.

Alguma ideia de como fazer isso em bash? Obrigado!

Editar : Correndo gleen jackman propus a resposta Eu recebo isto:

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.

    
por nunos 08.01.2015 / 01:06

4 respostas

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

remova echo se estiver satisfeito de que está funcionando. Não se preocupe se os comandos ecoados não mostrarem aspas, o script manipulará os arquivos com espaços corretamente.

Se você deseja remover os subdiretórios agora vazios:

find */ -depth -type d -exec echo rmdir '{}' \; 
    
por 08.01.2015 / 01:29
5

Usando a renomeação do perl:

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

OUTPUT

$ 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

  • Eu uso uma aparência negativa por trás (?<!\.) para não tocar na primeira ./
  • Eu mantenho os diretórios vazios, sinta-se à vontade para:

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

aviso http://pix.toile-libre.org/upload/original/1377510865.png Existem outras ferramentas com o mesmo nome que podem ou não ser capazes de fazer isso, então seja cuidadoso.

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 =)

Se não, para torná-lo o padrão (normalmente já é o caso) em Debian e derivado como Ubuntu :

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

(substitua /path/to/rename pelo caminho do comando perl's rename .

Se você não tiver esse comando, pesquise seu gerenciador de pacotes para instalá-lo ou faça isso manualmente

Por último, mas não menos importante, esta ferramenta foi originalmente escrita por Larry Wall, o pai do Perl.

    
por 08.01.2015 / 01:30
1

com pax ...

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

Isso criará um link físico no diretório atual para todos os arquivos em seus diretórios filhos com _ 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 são do seu agrado.

    
por 08.01.2015 / 12:57
0

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á, o qual poderá ser removido posteriormente.

$ ls
foo1_bar1.txt  foo1_bar2.txt  foo2_bar3.txt  foo2_bar4.txt  foo3_bar5.txt  foo3_bar6.txt
    
por 08.01.2015 / 15:33