Mover todos os subdiretórios de nível mais baixo (mas NÃO diretórios ou arquivos de nível médio) para um diretório de destino

0

Digamos que eu tenha um diretório source/ que tenha muitos subdiretórios. Alguns desses subdiretórios têm subdiretórios, e alguns desses subdiretórios têm sub-subdiretórios, e assim por diante.

O que eu quero fazer é encontrar recursivamente todos os subdiretórios de nível mais baixo (subdiretórios que não possuem mais subdiretórios) de source/ e movê-los para um novo diretório de destino.

Por exemplo, digamos que o original source/ seja assim:

/source/dir1               --Subdirectory without sub-subdirectory
/source/dir2               --Subdirectory with sub-subdirectory
/source/dir2/dir2.a        --Sub-subdirectory without sub-sub-subdirectory
/source/dir2/dir2.b        --Sub-subdirectory without sub-sub-subdirectory

Depois da operação, o diretório target deve ficar assim:

/target/dir1
/target/dir2.a
/target/dir2.b

Existe uma maneira de fazer isso com um comando de terminal?

    
por user287393 01.06.2014 / 16:30

2 respostas

1

Supondo que você esteja em um sistema de arquivos no qual os diretórios folha possuem exatamente 2 hard links, você pode usar uma combinação de find, xargs e mv da seguinte forma:

$ find . -type d -printf "%n %p\n"                   \
    | grep '^2 '                                     \
    | perl -ne 'chomp; s/[0-9]+\s+//; print "$_
$ find . -type d -printf "%n %p\n" | grep '2 ' | cut -d " " -f 2 | xargs -I'{}' mv -v '{}' /target/
";' \ | xargs -0 -I'{}' mv -v '{}' /target/

Isso usa o find para encontrar apenas diretórios e imprimir o número de hard links que esses diretórios possuem.

Em seguida, usamos grep para remover os que não são "folhas".

Em seguida, usamos Perl para cortar a contagem de hard-link e imprimir os arquivos separados por -0 .

Finalmente, isso nos permite usar xargs com o sinal %code% para mover os diretórios encontrados para o diretório de destino.

Usar nulos ( %code% ) em vez de novas linhas ou espaços é importante para arquivos com espaços neles. Se os nomes dos seus diretórios não tiverem espaços, você poderá simplificar um pouco.

$ find . -type d -printf "%n %p\n"                   \
    | grep '^2 '                                     \
    | perl -ne 'chomp; s/[0-9]+\s+//; print "$_
$ find . -type d -printf "%n %p\n" | grep '2 ' | cut -d " " -f 2 | xargs -I'{}' mv -v '{}' /target/
";' \ | xargs -0 -I'{}' mv -v '{}' /target/

Mas provavelmente é melhor prevenir do que remediar.

    
por Kaoru 01.06.2014 / 17:17
0

Uma abordagem pode ser usar find para obter cada diretório e passar os resultados para um segundo find e realizar a movimentação apenas se o segundo find retornar qualquer diretório abaixo do determinado, por exemplo,

while read -rd $'
find -depth -type d -execdir \
bash -c '[[ -z $(find "$0" -mindepth 1 -type d) ]] && mv -t path/to/target "$0"' {} +
' dir; do [[ -z $(find "$dir" -mindepth 1 -type d) ]] && mv -t path/to/target "$dir" done < <(find -depth -type d -print0)

ou

$ tree .
.
├── dir1
└── dir2
    ├── dir2.a
    └── dir2.b

por exemplo. dado

$ while read -rd $'
while read -rd $'
find -depth -type d -execdir \
bash -c '[[ -z $(find "$0" -mindepth 1 -type d) ]] && mv -t path/to/target "$0"' {} +
' dir; do [[ -z $(find "$dir" -mindepth 1 -type d) ]] && mv -t path/to/target "$dir" done < <(find -depth -type d -print0)
' dir; do [[ -z $(find "$dir" -mindepth 1 -type d) ]] && echo mv -t path/to/target "$dir"; done < <(find -depth -type d -print0) mv -t path/to/target ./dir1 mv -t path/to/target ./dir2/dir2.b mv -t path/to/target ./dir2/dir2.a

então

$ tree .
.
├── dir1
└── dir2
    ├── dir2.a
    └── dir2.b
    
por steeldriver 02.06.2014 / 00:47