Como posso mover todos os arquivos nos 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. Estou tentando algo como 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?

Coelhinho
fonte

Respostas:

14

Remova o {}from mv, mvo levará como diretório de destino, ignorando os diretórios pai:

find -type f -exec mv {} collection/ \;
Lekensteyn
fonte
ohh, isso não me ocorreu. Obrigado :)
Bunny Rabbit
Como eu disse na minha resposta à pergunta, essa é uma péssima idéia. Talvez o uso do argumento -maxdepth 1ajudasse.
Loevborg 7/11
Venha para pensar sobre isso, parece que eu li sua pergunta errado :) Desculpe.
Loevborg 7/11
@ loevborg: Adicionei "recursivamente" ao título agora. Se ainda houver confusão, edite-lo e melhorá-lo :)
Lekensteyn
1
uma variação mais rápida desta resposta éfind -type f -print0|xargs -0r mv -it colection/
hildred 4/14
5

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

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

mv $PWD/* $DEST

Como é que isso funciona? A expressão "$ PWD / *" se expande para os nomes de todos os arquivos nesse diretório. Esse 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 um ".". Para resolver isso, você deve dizer ao seu shell para incluir arquivos de ponto ao globbing. Para fazer isso, use

shopt -s dotglob

ao usar bash(e você provavelmente usa, a bashmenos que tenha alterado o padrão). Nesse shell, o comando acima também funcionará para arquivos de ponto.

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 arquivos de ponto. (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 realizado com zsh:

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

Aqui, a expressão **/*faz o globber descer recursivamente para subdiretórios. Os Dmeios "também selecionam arquivos de ponto"; os .meios "somente selecionam arquivos regulares, não diretórios".

Loevborg
fonte
Bem, eu queria recursiva em todos os sub-diretórios também, mas graças qualquer maneira como a informação é útil, se deparar com esta situação também um monte de vezes :)
Bunny Rabbit
Na verdade, encontrar não é um exagero para isso, globbing selecionará todas as correspondências, não apenas arquivos, mas também diretórios. Se você está se preocupa com o desempenho, você também pode usar algo como: find -type f -exec mv -t collection/ {} +. Consulte a página do manual sobre como isso funciona.
Lekensteyn
Lekensteyn, você está certo. Atualizei a resposta agora que entendi a pergunta.
Loevborg #
2
Resposta maravilhosa, pena que não seja particularmente relevante para a pergunta :).
Crazy2be