Como dissolver todas as subpastas

4

Existe um one-liner de linha de comando para mover todo o conteúdo de todas as subpastas diretas de uma pasta para a própria pasta e excluir as subpastas (que agora estão vazias)? Ou seja, eliminar um nível na hierarquia de pastas?

Para ser absolutamente claro, a estrutura subpasta mais profunda deve ser preservada.

Eu me deparei com isso algumas vezes agora, e fiquei um pouco desapontado que isso não parece ser uma característica do Dolphin, nem algo com o que outras pessoas estão lutando.

Eu suspeito que isso pode ter que ser dividido em dois, movendo o conteúdo das subpastas e excluindo as subpastas. No entanto, isso pode ter o efeito colateral indesejado de excluir subpastas vazias de segundo nível.

    
por oulenz 08.05.2017 / 10:45

3 respostas

5

Na verdade, não é uma frase de efeito real:

find . -mindepth 2 -maxdepth 2 -print -exec mv --backup=numbered -t . '{}' + \
&& find . -mindepth 1 -maxdepth 1 -type d -empty -delete

Primeiro, encontre tudo na subpasta com a profundidade exata 2 e mova-a para . . Em seguida, localize e exclua todas as pastas vazias no diretório atual.

  • se você tiver arquivos / pastas com o mesmo nome, eles serão renomeados com original_filename.~n~ (n significa 1, 2, 3 ...).
  • Observe que todas as subpastas vazias serão excluídas.

Atualização:

Não estou satisfeito com a solução acima. Muitas ressalvas e problemas. Por exemplo, quando --backup = numerado renomeia a pasta pai de sua pasta que você deseja mover ...

mkdir -p test/test
mv test/test . --backup=numbered
mv: cannot move 'test/test' to './test': No such file or directory

Use melhor um diretório temporário para evitar problemas. O diretório temporário deve estar no mesmo sistema de arquivos para evitar a necessidade de copiar os arquivos.

tmpdir=$(mktemp -d)
find . -mindepth 2 -maxdepth 2 -print -exec mv -b -t $tmpdir '{}' +
find . -mindepth 1 -maxdepth 1 -type d -empty -delete
mv -b $tmpdir/* .
rm $tmpdir
    
por RoVo 08.05.2017 / 11:32
1

Para proteger contra a exclusão de subdiretórios vazios, o IMO, a maneira mais simples é mover para um diretório temporário e, em seguida, renomear o diretório temporário para o diretório antigo. Digamos que o diretório em questão seja foo e você queira que foo/*/* se torne foo/* . Faça algo como:

tar c --remove-files foo | tar xv --strip-components=2 --backup=t --one-top-level=temp
mv temp foo
  • Com --remove-files , o primeiro tar excluirá os arquivos conforme eles são processados e, finalmente, excluirá foo .
  • Com --strip-components=2 , o segundo tar cortará o foo/*/ dos caminhos que está sendo extraído, portanto, foo/a/b se tornará b .
  • --backup=t é o mesmo que com cp ou mv - crie cópias de backup numeradas. No entanto, mv faz cópias de diretórios se eles tiverem o mesmo nome, mas tar mesclará os diretórios e fará backups de arquivos.
  • --one-top-level=temp diz a tar para criar um diretório chamado temp e extrair arquivos para lá.

Por exemplo:

$ tree bar
bar
├── a
│   ├── c
│   │   └── bar
│   ├── d
│   │   └── bar
│   ├── e
│   │   └── bar
│   └── f
│       └── bar
├── b
│   ├── c
│   │   └── bar
│   ├── d
│   │   └── bar
│   ├── e
│   │   └── bar
│   └── f
│       └── bar
└── c
    ├── c
    │   └── bar
    ├── d
    │   └── bar
    ├── e
    │   └── bar
    └── f
        └── bar

E depois de executar os comandos tar :

$ tar c --remove-files bar | tar xv --strip-components=2 --backup=t --one-top-level=temp
bar/a/e/
bar/a/e/bar
bar/a/f/
bar/a/f/bar
bar/a/c/
bar/a/c/bar
bar/a/d/
bar/a/d/bar
bar/b/e/
bar/b/e/bar
Renaming ‘temp/e/bar’ to ‘temp/e/bar.~1~’
bar/b/f/
bar/b/f/bar
Renaming ‘temp/f/bar’ to ‘temp/f/bar.~1~’
bar/b/c/
bar/b/c/bar
Renaming ‘temp/c/bar’ to ‘temp/c/bar.~1~’
bar/b/d/
bar/b/d/bar
Renaming ‘temp/d/bar’ to ‘temp/d/bar.~1~’
bar/c/e/
bar/c/e/bar
Renaming ‘temp/e/bar’ to ‘temp/e/bar.~2~’
bar/c/f/
bar/c/f/bar
Renaming ‘temp/f/bar’ to ‘temp/f/bar.~2~’
bar/c/c/
bar/c/c/bar
Renaming ‘temp/c/bar’ to ‘temp/c/bar.~2~’
bar/c/d/
bar/c/d/bar
Renaming ‘temp/d/bar’ to ‘temp/d/bar.~2~’

$ tree temp
temp
├── c
│   ├── bar
│   ├── bar.~1~
│   └── bar.~2~
├── d
│   ├── bar
│   ├── bar.~1~
│   └── bar.~2~
├── e
│   ├── bar
│   ├── bar.~1~
│   └── bar.~2~
└── f
    ├── bar
    ├── bar.~1~
    └── bar.~2~

4 directories, 12 files

Com a saída tar , é possível ver quando tar renomeou os arquivos para backup, permitindo que você acompanhe quais arquivos se tornaram quais backups.

Estou um pouco surpreso pelo fato de funcionar, mas você pode realmente fornecer o mesmo nome de diretório para --one-top-level e eliminar a necessidade de renomear. Apenas este pipeline é suficiente:

tar c --remove-files bar | tar xv --strip-components=2 --backup=t --one-top-level=bar
    
por muru 08.05.2017 / 12:33
-1
mv */* . && rmdir *

Mova tudo em subdiretórios para os diretórios atuais. O rmdir não irá deletar diretórios a menos que eles estejam vazios, então a segunda parte apenas exclui diretórios vazios.

    
por Harry Harrison 08.05.2017 / 12:32