Mover arquivos diferentes para outra pasta

2

OK, eu tenho uma biblioteca muito grande do iTunes e recentemente decidi organizá-la de uma maneira muito mais organizada do que apenas jogar todas as minhas músicas em uma pasta e esperar pelo melhor. Então, depois de muitas horas de entrada e saída de arquivos ou diretórios e de esperar que o iTunes faça o que o iTunes faz, de alguma forma acabei com algumas músicas perdidas. Se foi 1 ou 2, então, eu posso encontrá-los sozinho. Mas estou perdendo um pouco mais de 30000, então não estou muito interessada na ideia de procurá-los manualmente.

Então, minha pergunta é: "Existe uma maneira para eu, em um ambiente linux, encontrar todos os arquivos que estão em um diretório, que não estão em outro, e então movê-los?"

Minha estrutura de pastas parece um pouco assim:

  • Diretório pai (disco rígido externo)

    • Arquivos ausentes (há 4 dessas pastas
      • Centenas de pastas com nomes de artistas (algumas têm arquivos .mp3 aqui, outras têm outra subpasta e outras têm outra subpasta novamente)
    • Diretório Parent Itunes (onde o iTunes mantém músicas, arquivos de listas de reprodução, podcasts etc.)

(eu sou muito ruim em listas nessas questões ^) Então, o que eu preciso, é mover qualquer coisa que é no diretório "Missing Files" que não é na "Pasta iTunes"

Obrigado por qualquer ajuda antecipadamente, eu realmente agradeço.

Observação: só quero mover os arquivos de mp3 das pastas, não das próprias pastas.

    
por Zachary Wight 21.08.2016 / 04:12

1 resposta

1

Supondo que você tenha uma estrutura de diretório como:

music
  |- source
      |- foobar
      |- spamegg
      |- ...
  |- dest

e você precisa mover todos os arquivos .mp3 em qualquer nível de subdiretórios de music/source/ para music/dest/ apenas se o arquivo ainda não estiver presente em music/dest/ .

Se assim for, executando todos os comandos abaixo do diretório music/ :

  • Crie uma matriz contendo todos os arquivos .mp3 em music/source , operação recursiva:

    shopt -s globstar  ## Enables recursive search
    source_files=( source/**/*.mp3 )
    
  • Faça o mesmo com o diretório music/dest/ e remova a parte do diretório dos nomes de arquivo:

    dest_files=( dest/**/*.mp3 )
    dest_files=( ${dest_files[@]} )
    
  • Itere os arquivos de origem e verifique se o arquivo já existe no destino, se não mv o arquivo para music/dest/ :

    for i in "${source_files[@]}"; do [[ ! ${dest_files[@]} =~ ${i##*/} ]] && \
             echo mv -i "$i" dest/; done 
    

    echo é para fazer o dry-run, se estiver satisfeito, basta remover echo :

    for i in "${source_files[@]}"; do [[ ! ${dest_files[@]} =~ ${i##*/} ]] && \
             mv -i "$i" dest/; done
    

Formulário com script:

#!/usr/bin/env bash
shopt -s globstar
source_files=( source/**/*.mp3 )
dest_files=( dest/**/*.mp3 )
dest_files=( ${dest_files[@]} )
for i in "${source_files[@]}"; do [[ ! ${dest_files[@]} =~ ${i##*/} ]] && \
     mv -i "$i" dest/; done

Você pode obviamente usar caminhos absolutos, alterar os caminhos relevantes para atender às suas necessidades.

Advertências:

  • Todos os arquivos .mp3 de origem e destino são colocados em matrizes, precisam de memória extra, não devem ser um problema em sistemas modernos

  • O teste de associação leva tempo, novamente não deve ser perceptível nos sistemas modernos

Exemplo:

music$ tree 
.
├── dest
│   ├── 1.mp3
│   ├── 2.mp3
│   ├── 3.mp3
│   ├── 7.mp3
│   ├── 8.mp3
│   └── 9.mp3
└── source
    ├── bar
    │   ├── 10.mp3
    │   ├── 6.mp3
    │   ├── 7.mp3
    │   ├── 8.mp3
    │   └── 9.mp3
    └── foo
        ├── 1.mp3
        ├── 2.mp3
        ├── 3.mp3
        ├── 4.mp3
        └── 5.mp3

music$ shopt -s globstar

music$ source_files=( source/**/*.mp3 )

music$ dest_files=( dest/**/*.mp3 )

music$ dest_files=( ${dest_files[@]} )

music$ for i in "${source_files[@]}"; do [[ ! ${dest_files[@]} =~ ${i##*/} ]] && echo mv "$i" dest/; done
mv source/bar/10.mp3 dest/
mv source/bar/6.mp3 dest/
mv source/foo/4.mp3 dest/
mv source/foo/5.mp3 dest/

music$ for i in "${source_files[@]}"; do [[ ! ${dest_files[@]} =~ ${i##*/} ]] && mv "$i" dest/; done

music$ tree 
.
├── dest
│   ├── 10.mp3
│   ├── 1.mp3
│   ├── 2.mp3
│   ├── 3.mp3
│   ├── 4.mp3
│   ├── 5.mp3
│   ├── 6.mp3
│   ├── 7.mp3
│   ├── 8.mp3
│   └── 9.mp3
└── source
    ├── bar
    │   ├── 7.mp3
    │   ├── 8.mp3
    │   └── 9.mp3
    └── foo
        ├── 1.mp3
        ├── 2.mp3
        └── 3.mp3
    
por heemayl 21.08.2016 / 07:10