Mova todos os arquivos com uma certa extensão de vários subdiretórios para um diretório

43

Eu tenho um monte de arquivos .zip em vários diretórios:

Fol1/Fol2
Fol3
Fol4/Fol5

Como eu moveria todos eles para uma pasta base comum?

InquilineKea
fonte
Deseja manter a estrutura de diretórios? Deseja mover os diretórios ou apenas os arquivos zip?
jordanm
Eu só quero mover os arquivos zip. Eu realmente não me importo com os diretórios - eles podem ser deixados sozinhos ou excluídos.
InquilineKea

Respostas:

55

Vá para o diretório de nível superior da árvore que contém os arquivos zip ( cd …) e execute

mv **/*.zip /path/to/single/target/directory

Isso funciona imediatamente no zsh. Se o seu shell for bash, você precisará executar shopt -s globstarprimeiro (você pode e deve colocar este comando no seu ~/.bashrc). Se o seu shell for ksh, você precisará executar set -o globstarprimeiro (coloque-o no seu ~/.kshrc).

Como alternativa, use find, que funciona em qualquer lugar sem preparação especial, mas é mais complicado:

find . -name '*.zip' -exec mv {} /path/to/single/target/directory \;

Se você deseja remover diretórios vazios posteriormente, no zsh:

rmdir **/*(/^Fod)

No bash ou ksh:

rmdir **/*/

e repita enquanto houver diretórios vazios para remover. Como alternativa, em qualquer shell

find . -depth -type d -empty -exec rmdir {} \;
Gilles 'SO- parar de ser mau'
fonte
O primeiro findcomando acima funcionou no bash, mas teve que mudar para find . -nameetc para fazê-lo funcionar.
21417 Jeffrey Thompson
1
@ Jeff .está implícito para o GNU find, mas não para outros, eu o adicionei explicitamente.
Gilles 'SO- stop be evil'
13

Se você quiser apenas mover os .ziparquivos, poderá fazer algo como

mkdir ./zipfiles
find . -name "*.zip" -exec mv "{}" ./zipfiles \;
Bernhard
fonte
3

Se você estiver usando o bash versão 4 ou superior ou zsh, também poderá usar globbing recursivo:

mv **/*.zip /path/to/move/zip/files/to

Isso moverá SOMENTE os arquivos e não seus caminhos relativos; portanto, podem ocorrer colisões.

SuperMagic
fonte
o que você quer dizer com caminhos relativos?
Kunok
2

Este é seguro ao mover dados e livre de erros, o que é compatível com a maioria das distribuições, independentemente das versões. Este comando varrerá subdiretórios e depois moverá ou copiará para o novo diretório de destino.

find . -name *.flac -exec mv '{}' "./flac/" ";"
  • Execute este comando no diretório principal que contém subdiretórios com os arquivos que você deseja mover.
  • Onde você pode mudar *.flacpara algo como *.zipno seu caso. Ou *.docqualquer extensão funciona.
  • e mvé o comando para mover arquivos, ou você pode usar cppara copiar dados em vez de mover.
  • ./flac/é o diretório de destino para o qual desejo mover todos os arquivos FLAC. Você também pode fornecer um caminho completo, como/home/myid/flac/

Exemplo completo. (neste caso, existem muitos subdiretórios com o nome do artista de música em /home/myid/Music/e, em seguida, os arquivos FLAC estão em diferentes níveis de subdiretórios. Como não preciso de pastas de artistas, mas quero ter todos os arquivos FLAC em um diretório em/home/myid/Music/flac/

cd /home/myid/Music
mkdir flac
find . -name *.flac -exec mv '{}' "./flac/" ";"
cd flac
ls

Em seguida, ele exibirá todos os arquivos FLAC.

Seandex
fonte
o que ;faz?
Francesco Boi
@FrancescoBoi, certifique-se de esperar até que o comando bash na mesma linha termine seu trabalho. e depois passe para a próxima linha de comandos do bash. Isso é útil para comandos que contêm scripts como .pl ou python, porque o bash irá executá-lo e depois pular para a próxima linha, para segurança, eu uso; após os comandos que levam tempo ou script, caso o bash ignore.
Seandex
0

Como um hack do bash, você pode usar o poder de tar:

(cd origin/;find . -exec file --mime-type "{}" \;|grep "application/zip"|cut -d ':' -f 1|xargs tar cf -)|(cd target/; tar xf -) && rm -fr origin/

Isso tem a vantagem de não depender de extensões de arquivo, pois usa o filecomando para escolher os arquivos a serem movidos e preserva a estrutura de diretórios, mas não funciona com caminhos que contêm espaços.

A final rmestá lá apenas para remover os arquivos originais (porque @InquilineKea diz que ele não se importa com a pasta original no comentário).

Obviamente, isso é particularmente adequado se as pastas de origem / destino / estiverem em discos diferentes. Caso contrário, as outras soluções propostas são mais eficientes (mesmo que sejam baseadas em convenções de nomenclatura, em vez do fileconteúdo).

Giacomo Tesio
fonte
0

Supondo que você tenha as versões GNU de find e mv, o seguinte será mais eficiente do que as respostas existentes baseadas em localização:

find . -name '*.zip' -exec mv --target-directory='/path/to/outputdir' '{}' +

Usar um +no final do find -exec significa que uma lista de arquivos será passada para o comando mv, em vez de executar um comando mv por arquivo encontrado. No entanto, uma limitação disso é que você só pode colocar o '{}' no final do comando, o que requer o uso da opção mv --target-directory e, tanto quanto eu sei, é um GNU-ism.

evilsoup
fonte