Como posso mover todos os arquivos em subdiretórios recursivamente para um único diretório?

10

Estou tentando coletar todos os arquivos no diretório atual e todos os subdiretórios em um diretório. Eu estou tentando algo parecido com o seguinte

find -type f -exec mv {} collection/{} \; 

o comando acima não funcionará porque o segundo {} fornece o caminho completo, como posso coletar todos os arquivos?

    
por Bunny Rabbit 07.05.2011 / 12:15

2 respostas

13

Remova o {} de mv , mv o tomará como diretório de destino, ignorando qualquer diretório pai:

find -type f -exec mv {} collection/ \;
    
por Lekensteyn 07.05.2011 / 12:33
5

Em vez de usar find (que faz bem o trabalho), você também pode usar o shell para esse fim.

Digamos que você queira todos os arquivos de $ PWD para $ DEST. A tentativa natural seria:

mv $PWD/* $DEST

Como isso funciona? A expressão "$ PWD / *" é expandida para os nomes de todos os arquivos nesse diretório. Este recurso de shell é chamado de "globbing". O último argumento de mv é o diretório de destino. Se você tiver muitos arquivos, isso não funcionará porque o comprimento da linha de comando é limitado.

Mas a solução tem o problema de omitir arquivos de ponto - ou arquivos "ocultos", arquivos e diretórios cujo nome começa com ".". Para resolver isso, você tem que dizer ao seu shell para incluir arquivos de ponto quando globbing. Para fazer isso, use

shopt -s dotglob

ao usar bash (e você provavelmente usará bash , a menos que você tenha alterado o padrão). Neste shell, o comando acima também funcionará para os dotfiles.

Como um aparte, em zsh , você tem a opção de escolher isso caso a caso. Para fazer isso, coloque

setopt extendedglob

no seu .zshrc . Então você pode usar

mv $PWD/*(D) $DEST

para mover todos os arquivos, incluindo os dotfiles. (O "D" tem o efeito de ativar temporariamente a opção "GLOB_DOTS").

Agora, a pergunta original era mover todos os arquivos regulares (não diretórios) de todos os subdiretórios e seus subdiretórios para um único diretório. Isso pode ser feito com zsh :

mv $PWD/**/*(D.)

Aqui, a expressão **/* faz a globalização descer recursivamente em subdiretórios. O D significa "também selecione dotfiles", o . significa "apenas selecione arquivos regulares, não diretórios".

    
por loevborg 07.05.2011 / 14:22