Linux: mover arquivos de diretórios diferentes com o mesmo nome para um enquanto os renomeia

Linux: mover arquivos de diretórios diferentes com o mesmo nome para um enquanto os renomeia

Copiei em lote meus CDs antigos para Track1.mp3. O problema é que cada diretório de CD possui Track1.mp3, então quando eu os movo para /Music, eles sobrescrevem!

Existe possivelmente um script bash ou comando mv paramover.mp3s de vários subdiretórios com o mesmo nome de arquivo em um único diretório enquanto os renomeia se esse nome já existir no LINUX?

Responder1

Provavelmente você desejará renomeações "amigáveis". Vamos supor que você tenha uma sutura como

Artist1-+
        +-AlbumA-+
        |        +-Track1.mp3
        |        +-Track2.mp3
        +-AlbumB-+
                 +-Track1.mp3
                 +-Track2.mp3
Artist2-+
        +-AlbumX-+
        |        +-Track1.mp3
        |        +-Track2.mp3
        +-AlbumY-+
        |        +-Track1.mp3
        |        +-Track2.mp3

Agora você gostaria que o diretório único contivesse algo como

Artist1-AlbumA-Track1.mp3
Artist1-AlbumA-Track2.mp3
...
Artist2-AlbumY-Track1.mp3
Artist2-AlbumY-Track2.mp3

Isto pode ser conseguido com um simples bashloop

for M in */*/*.mp3; do
  TRACK=$(basename "$M")
  ALBUM=$(basename $(dirname "$M"))
  ARTIST=$(basename $(dirname $(dirname "$M")))
  mv "$M" "$TARGET_DIR/$ARTIST-$ALBUM-$TRACK"
done

Responder2

Os comandos cpe mvsuportam esta funcionalidade através da --backupopção.

Demanual:

   --backup[=CONTROL]
          make a backup of each existing destination file

   -b     like --backup but does not accept an argument

[...]

O sufixo de backup é '~', a menos que seja definido com --suffix ou SIMPLE_BACKUP_SUFFIX. O método de controle de versão pode ser selecionado através da opção --backup ou através da variável de ambiente VERSION_CONTROL. Aqui estão os valores:

   none, off
          never make backups (even if --backup is given)

   numbered, t
          make numbered backups

   existing, nil
          numbered if numbered backups exist, simple otherwise

   simple, never
          always make simple backups

Então, por exemplo, mv --backup=t <source_file> <dest_file>deve funcionar.

Responder3

De acordo com a comunidade Linux e commandlinefu.com, esse recurso conveniente não é possível em nenhuma versão até o momento.

Atualmente não há comando e nenhuma maneira segura, via linha de comando, de mover arquivos de vários diretórios e subdiretórios com o mesmo nome, para um único diretório, sem substituí-los.

Fontes: commandlinefu.com, askubuntu.com, linuxquestions.org, superuser.com

Responder4

Presumo que você tenha uma estrutura de pastas como esta:

$ tree .
.
├── artist1
│   ├── albuma
│   │   └── Track1.mp3
│   └── albumb
│       └── Track1.mp3
└── artist two
    ├── album one
    │   └── Track1.mp3
    └── album two
        └── Track1.mp3

Primeiro, cdpara a pasta pai da sua coleção de MP3 (pasta pai de artist1).

Agora, se você executar o seguinte findcomando, verá uma saída como esta:

$ find . -name '*.mp3' -exec bash -c 'echo mv -v "$1" /tmp/music/$(echo "$1" | sed "s/\.\///" | tr " /" "-")' bash {} \;
mv -v ./artist two/album one/Track1.mp3 /tmp/music/artist-two-album-one-Track1.mp3
mv -v ./artist two/album two/Track1.mp3 /tmp/music/artist-two-album-two-Track1.mp3
mv -v ./artist1/albuma/Track1.mp3 /tmp/music/artist1-albuma-Track1.mp3
mv -v ./artist1/albumb/Track1.mp3 /tmp/music/artist1-albumb-Track1.mp3
  • findcoleta todos os caminhos para os arquivos MP3, por exemplo, ./artist two/album one/Track1.mp3e os passa bashvia-exec
  • $(echo "$1" | sed "s/\.\///" | tr " /" "-")é usado para modificar o nome do arquivo de saída. sedremove o primeiro ./e trconverte todos os caracteres de espaço e /para -.

É essencial que você execute findcomo .diretório inicial, caso contrário o caminho de saída (relativo) não será modificado corretamente. Mude /tmp/music/para o caminho da sua biblioteca de música.

Se a saída parecer boa para você, remova a primeira echoe execute o comando novamente.

Saída:

$ find . -name '*.mp3' -exec bash -c 'mv -v "$1" /tmp/music/$(echo "$1" | sed "s/\.\///" | tr " /" "-")' babbsh {} \;
'./artist two/album one/Track1.mp3' -> '/tmp/music/artist-two-album-one-Track1.mp3'
'./artist two/album two/Track1.mp3' -> '/tmp/music/artist-two-album-two-Track1.mp3'
'./artist1/albuma/Track1.mp3' -> '/tmp/music/artist1-albuma-Track1.mp3'
'./artist1/albumb/Track1.mp3' -> '/tmp/music/artist1-albumb-Track1.mp3'

informação relacionada