Mover os arquivos para cima por um diretório por critério de profundidade

2

Eu tenho uma árvore de diretórios que se parece com isso (simplificado, na verdade, existem centenas de pastas):

.
├── a
│   └── b
│       └── a.h5
├── b
│   ├── b
│   │   └── e.h5
│   └── c
│       ├── a.h5
│       └── b.h5
├── c
│   └── b
│       └── a.h5
├── d
│   ├── a.h5
│   └── e.h5
└── e
    └── e.h5

Basicamente, alguns arquivos .h5 estão na profundidade 1 (ex. d/a.h5 , e/e.h5 ) e alguns arquivos são profundidade 2 (ex. b/b/e.h5, b/c/b.h5 , ...)

Eu gostaria de subir apenas os arquivos na profundidade 2, para que eles fiquem todos na profundidade 1, como em:

.
├── a
│   └── a.h5
├── b
│   ├── e.h5
│   ├── a.h5
│   └── b.h5
├── c
│   └── a.h5
├── d
│   ├── a.h5
│   └── e.h5
└── e
    └── e.h5

Eu sei que */*/*.h5 corresponde aos arquivos em que estou interessado (testado via ls */*/*.h5 ), mas eu tentei mv */*/*.h5 */*.h5 e ele fez uma bagunça.

Arquivos duplicados seriam idealmente gerenciados por renomeação, mas também a solicitação está correta. Como devo proceder?

P.S: Eu vi:

Mas ambos se aplicam a diretórios únicos.

    
por Enoon 27.10.2015 / 11:40

3 respostas

3

Indo da sua estrutura de diretórios:

$ tree
.
├── a
│   └── b
│       └── a.h5
├── b
│   ├── b
│   │   └── e.h5
│   └── c
│       ├── a.h5
│       └── b.h5
├── c
│   └── b
│       └── a.h5
├── d
│   ├── a.h5
│   └── e.h5
└── e
    └── e.h5

12 directories, 8 files

Use este loop for :

$ for f in */*/*.h5; do mv -v -- "$f" "${f%/*}/../"; done
»a/b/a.h5“ -> »a/b/../a.h5“
»b/b/e.h5“ -> »b/b/../e.h5“
»b/c/a.h5“ -> »b/c/../a.h5“
»b/c/b.h5“ -> »b/c/../b.h5“
»c/b/a.h5“ -> »c/b/../a.h5“

O resultado :

$ tree
.
├── a
│   ├── a.h5
│   └── b
├── b
│   ├── a.h5
│   ├── b
│   ├── b.h5
│   ├── c
│   └── e.h5
├── c
│   ├── a.h5
│   └── b
├── d
│   ├── a.h5
│   └── e.h5
└── e
    └── e.h5

12 directories, 8 files

Explicação :

for f in */*/*.h5; do mv -v -- "$f" "${f%/*}/../"; done
  • for f in */*/*.h5 faz um loop por todos os arquivos desejados
    • mv -v -- move-os, verbosamente. -- impede que nomes de arquivos com traços sejam interpretados como argumentos.
    • "$f" do nome do arquivo original
    • ${f%/*}/../ o nome do diretório que contém o arquivo ../ adicionado. Esse caminho é interpretado como "um diretório para cima".
por 27.10.2015 / 11:54
3

Isso deve ser um começo:

find . -mindepth 3 -maxdepth 3 -type f -execdir mv -i -v {} .. \;

o mv -i pede para substituir os arquivos existentes. -execdir muda para o diretório do arquivo antes de fazer o comando.

    
por 27.10.2015 / 11:55
1

tente

 for x in */*/*.h5
 do
    mv "$x" "$(dirname $(dirname $x))"
 done

se você não tem caracteres estranhos em seus nomes de diretório.

Ou, alternativamente:

ls */*/*.h5 | awk -F/ '{print "mv \"%s\"  \"%s/%s\" \n",$0,$1,$3 ;}' | bash

você pode remover | bash para obter uma prévia.

    
por 27.10.2015 / 11:53