Achatando a hierarquia de diretórios preservando os nomes de diretório no novo nome de diretório

7

Eu basicamente quero ir disso:

.
├── Alan Walker
│   ├── Different World
│   │   ├── 01 Intro.mp3
│   │   ├── 02 Lost Control.mp3
│   │   └── cover.jpg
│   └── Same World
│       ├── 01 Intro.mp3
│       └── 02 Found Control.mp3
├── Aurora
│   └── Infections Of A Different Kind Step 1
│       ├── 01 Queendom.lrc
│       ├── 02 Forgotten Love.lrc
│       └── 03 Gentle Earthquakes.mp3
└── Guns N' Roses
    └── Use Your Illusion I
        ├── 01 Right Next Door To Hell.lrc
        ├── 01 Right Next Door To Hell.mp3
        ├── 02 Dust N' Bones.lrc
        └── 02 Dust N' Bones.mp3

para isso:

.
├── Alan Walker - Different World
│   ├── 01 Intro.mp3
│   ├── 02 Lost Control.mp3
│   └── cover.jpg
├── Alan Walker - Same World
│   ├── 01 Intro.mp3
│   └── 02 Found Control.mp3
├── Aurora - Infections Of A Different Kind Step 1
│   ├── 01 Queendom.lrc
│   ├── 02 Forgotten Love.lrc
│   └── 03 Gentle Earthquakes.mp3
└── Guns N' Roses - Use Your Illusion I
    ├── 01 Right Next Door To Hell.lrc
    ├── 01 Right Next Door To Hell.mp3
    ├── 02 Dust N' Bones.lrc
    └── 02 Dust N' Bones.mp3

Nenhuma das soluções existentes que encontrei incluiu renomear o próprio diretório. Seria ótimo poder fazer isso com o zmv, mas não consigo descobrir como.

aksh1618
fonte
2
Não uma solução completa, por isso não é uma resposta: easytagpode deixá-lo fazer isso, mas apenas para arquivos de áudio - Eu não acho que ele vai passar tampas, etc.
RVS
2
Poderia haver mais de um álbum para um artista específico em um diretório de artistas? A estrutura tem sempre três níveis de profundidade?
nohillside
1
@nohillside Sim, pode haver mais de um álbum para um artista. E sim, a estrutura tem sempre três níveis de profundidade.
aksh1618

Respostas:

9

Zsh

Não testado:

zmv -Q '(*)/(*)(/)' '$1 - $2'
rmdir -- *(/^F)

A segunda linha remove todos os diretórios vazios, mesmo aqueles que não tinham um arquivo antes. É possível contornar isso com um mvwrapper personalizado que registra de quais diretórios ele move as coisas.

Observe que isso percorre links simbólicos para diretórios no diretório atual.

Utilitário de renomeação do Linux

Não testado.

rename / ' - ' */*/
rmdir -- */ 2>/dev/null

Observe que isso percorre links simbólicos para diretórios no diretório atual e em seus subdiretórios. A segunda linha remove todos os diretórios vazios, mesmo aqueles que não tinham um arquivo antes.

Script de renomeação do Perl

Não testado.

prename 's~/~ - ~' */*/
rmdir -- */ 2>/dev/null

Observe que isso percorre links simbólicos para diretórios no diretório atual e em seus subdiretórios. A segunda linha remove todos os diretórios vazios, mesmo aqueles que não tinham um arquivo antes.

Aqui está uma abordagem mais complexa que remove apenas os diretórios dos quais renomeou algo. Novamente, não testado.

prename 's~([^/]+)/~$1 - ~ and ++$d{$1}; END {map {rmdir} keys %d}' */*/
Gilles 'SO- parar de ser mau'
fonte
12

Algo assim talvez?

#!/bin/sh

for topdir in */; do
    topdir_name=$( basename "$topdir" )

    for subdir in "$topdir"/*/; do
        subdir_name=$( basename "$subdir" )

        newdir="$topdir_name - $subdir_name"
        if mkdir "$newdir"; then
            mv "$subdir"/* "$newdir"
            rmdir "$subdir"
        fi
    done

    rmdir "$topdir"
done

Isso passa por todos os diretórios de nível superior no diretório atual (os nomes das bandas). Para cada diretório, ele passa por seus subdiretórios (os nomes dos álbuns). Para cada par de nome de banda e nome de álbum, um novo diretório é criado e os arquivos do subdiretório são movidos para ele. Os subdiretórios do álbum são removidos quando processados, assim como os diretórios originais de nível superior da banda.

As rmdirchamadas falharão se algum diretório contiver nomes de arquivos ocultos ou se algum dos novos diretórios falhar ao ser criado.

Este é um código totalmente não testado. Execute-o em uma cópia de backup dos seus arquivos.

Kusalananda
fonte
Quero dizer, sim, algo como funcionaria, mas estou procurando uma solução de uma ou duas linhas, para rodar facilmente a partir do terminal. Alguns find / sed / zmv mágica :)
aksh1618
10
Coloque ot em um script e - boom - ele se torna um one-liner.
Hans-Martin Mosner 02/01/19
4

Estrategicamente, em vez de mover arquivos, você considerou deixar a estrutura atual no lugar e criar links para a nova estrutura desejada?

Taticamente, um padrão que fará o trabalho é assim:

find . -mindepth 2 -maxdepth 2 -type d -print0 | xargs -0n1 bash -c \
  'b=$(basename "$(dirname "$1")"); a=$(basename "$1"); echo ln -s "$1" "$b-$a"' {}
  • findlocaliza todos os diretórios exatamente com dois níveis de profundidade do diretório de trabalho atual, que deve ser o diretório que contém as bandas: assim, dois níveis de profundidade são os nomes dos álbuns abaixo dos nomes das bandas. 1
  • xargs consome cada caminho que contém um álbum e chama o script bash embutido.
  • bash -c '...'toma o caminho do álbum como seu primeiro argumento, dividindo-o em duas partes: a banda ( $b) e o álbum ( $a). Por fim, o script reúne os nomes no formato desejado e vincula o novo nome do diretório ao diretório original.

Observe que, neste exemplo, os links seriam criados no mesmo diretório a partir do qual você inicia, que também é onde estão os nomes das bandas.

Você pode - e deve - ajustar a lnestratégia acima para corresponder à sua intenção. mvcom os caminhos certos se você deseja reorganizar fisicamente ou lnse deseja criar uma "visualização" conveniente sobre a mídia. As partes importantes dentro do script bash são:

  • $bo nome da banda. Sempre citá-lo: "$b".
  • $ao nome do álbum. Sempre citá-lo: "$a".
  • $1o caminho físico para o diretório do álbum. Sempre citá-lo: "$1".

1 Acredito que m{ax,in}depthsejam suportados pelo GNU e por algum BSD find, mas não pelo POSIX: nesse caso, conte com */*uma ginástica shell semelhante ou semelhante.

bispo
fonte
1
Eu gosto desta resposta ... você também pode fazer hardlinks, em seguida, excluir a estrutura de pastas de idade quando você está satisfeito
Thomas Zwaagstra
@ThomasZwaagstra Isso não é diferente do que mover os arquivos
Darkhogg
1
@Darkhogg Exactly! O OP estava procurando um liner para mover os arquivos. Usando hardlinks com esta solução seria quase conseguir isso, exceto que você teria um estágio intermediário "preview" antes de excluir os arquivos originais
Thomas Zwaagstra