Qual é a maneira mais eficiente de mover um grande número de arquivos que residem em um único diretório?

11

CentOS 5.x

Peço desculpas se esta é uma pergunta repetida. Já vi muitas perguntas semelhantes (sobre a exclusão de arquivos), mas não exatamente o mesmo cenário.

Eu tenho um diretório contendo centenas de milhares de arquivos (possivelmente mais de um milhão) e, como uma correção de curto prazo para um problema diferente, preciso mover esses arquivos para outro local.

Para fins de discussão, digamos que esses arquivos residam originalmente /home/foo/bulk/e desejo movê-los para/home/foo2/bulk2/

Se eu tentar mv /home/foo/bulk/* /home/foo2/bulk2/ , recebo um erro "muitos argumentos".

O Sr. Google me disse que uma alternativa para excluir arquivos em massa seria executar o find. Algo como: find . -name "*.pdf" -maxdepth 1 -print0 | xargs -0 rm

Seria bom se eu estivesse excluindo coisas, mas, neste caso, quero mover os arquivos ... Se eu digitar algo como find . -name "*" -maxdepth 1 -print0 | xargs -0 mv /home/foo2/bulk2/bash, reclama que o arquivo não é um diretório.

Qual é o melhor comando a ser usado aqui para mover os arquivos em massa de um diretório para outro?

Mike B
fonte

Respostas:

16

Aproveitando mva -topção do GNU para especificar o diretório de destino, em vez de confiar no último argumento:

find . -name "*" -maxdepth 1 -exec mv -t /home/foo2/bulk2 {} +

Se você estivesse em um sistema sem a opção, poderia usar um shell intermediário para obter os argumentos na ordem correta ( find … -exec … +não suporta a colocação de argumentos extras após a lista de arquivos).

find . -name "*" -maxdepth 1 -exec sh -c 'mv "$@" "$0"' /home/foo2/bulk2 {} +
Gilles 'SO- parar de ser mau'
fonte
Você pode usar find ... -exec sh -c 'blah "$ @" blah' sh {} + "(o" truque de shell ") para lidar com problemas relacionados à ordenação de argumentos. Existem vários exemplos disso nos findutils ( info) documentação; procure por "sh -c".
James Youngman
5

Considerando mvo diretório pai em vez dos arquivos:

mv /home/foo/bulk /home/foo2/bulk2 && mkdir /home/foo/bulk

(Mas pode causar problemas, se /home/foo/bulknecessário, a cada momento.)

Scott
fonte
1
Eu acrescentaria a isso, caso o diretório de destino exista, mova os arquivos no diretório de destino para o diretório de origem (o principal) e renomeie o diretório.
sbenitezb
Obrigado - ótima sugestão. Nesse caso, o diretório deve existir a todo momento. Ótima idéia embora.
Mike B
Tenho que admitir que não entendo o que essa resposta faz. Por que mkdir? E o dir "existindo a todo momento" ou não? Por que isso aceleraria as coisas?
Monica Heddneck
Sei que esse comentário tem um ano, mas o último tinha cinco anos, então achei que seria melhor responder ... Suas duas primeiras perguntas estão correlacionadas. O mkdiré porque a pasta inteira e tudo dentro dele seria movido para o outro diretório e já não existem no diretório antigo. Ele garante que o diretório antigo ainda exista. No entanto, isso não seria suficiente se houvesse um serviço em execução constante que dependesse do primeiro diretório sempre existente, porque ele é movido e recriado. Não torna nada mais rápido, apenas mais simples, fornecendo menos argumentos.
Lucas Leblanc
0

Só por variedade, gosto de usar o cpio em alguns casos como este.

find tmp |cpio -v  -p --make-directories --sparse tmp2
Arthur Ulfeldt
fonte
1
Se a origem e o destino estiverem no mesmo sistema de arquivos, essa abordagem poderá ser muito ineficiente (cópia desnecessária). Também é sempre melhor usar -print0e -0opções.
Pabouk
0

Com o GNU mv:

find . -mindepth 1 -exec mv -t /tmp {} +

Em sistemas como o OS X que não possuem, mv -tmas possuem -print0e xargs -0:

find . -mindepth 1 -print0|xargs -0 -I, mv , /tmp

Ou se os nomes dos arquivos não contiverem espaços, aspas, barras invertidas ou novas linhas (com OS X xargs) ou aspas, barras invertidas ou novas linhas (com GNU xargs):

ls|xargs -I, mv , /tmp
Lri
fonte
-3

Por um tempo especificado, tente o seguinte:

find . -name "*" -type f -mtime +7 -exec mv -t /folder/to/transfer/files {} +
brim
fonte