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
emmusic/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 paramusic/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 removerecho
: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