Eu tenho milhões de imagens no meu servidor em nuvem ubuntu. Quando movo uma pasta completa contendo 12 milhões de imagens usando o mv
comando, isso acontece quase instantaneamente. No entanto, quando eu mv
apenas imagens (não a pasta), leva algum tempo. Existe uma maneira de mover todas as imagens tão rapidamente quanto as pastas?
Isto é o que está acontecendo:
pasta src tem 12 milhões de imagens e eu a movo para a pasta dst usando
$ mv src ../dst
Acontece imediatamente
Dentro da pasta src, faço isso para mover:
find -maxdepth 1 -name '*.jpg' -exec mv -t ../../dst/ {} +
Isso leva algum tempo.
Existe uma maneira de acelerar o segundo processo?
dst
está em uma partição enquanto../../dst
está em outra.{}
argumentos onde os nomes dos arquivos seriam expandidos.find
.find ... -exec mv -t ../../dst/ {} \;
chamariamv
uma vez por arquivo;find ... -exec mv -t ../../dest {} +
seria muito mais rápido, copiando o máximo de arquivos por chamada possível, mas ainda não tão rápido quanto mover o próprio diretório, conforme explicado por dadexix86 .Respostas:
TL; DR : Não
Para uma quantidade menor de arquivos, você não precisaria
find
, mas mesmo neste caso simplificado e menor, se você apenaslevará mais tempo do que mover todo o diretório de uma só vez.
Por quê? O ponto é entender o que
mv
faz.Em resumo,
mv
move um número (que identifica um diretório ou arquivo) de um inode (o diretório que o contém) para outro, e esses índices são atualizados no diário do sistema de arquivos ou no FAT (se o sistema de arquivos é implementado dessa maneira).Se a origem e o destino estiverem no mesmo sistema de arquivos, não há movimento real dos dados, apenas muda a posição, o ponto ao qual eles estão anexados.
Então, quando você
mv
um diretório, você está fazendo esta operação uma vez .Mas quando você move 1 milhão de arquivos, está fazendo essa operação 1 milhão de vezes .
Para dar um exemplo prático, você tem uma árvore com muitos galhos. Em particular, há um nó ao qual 1 milhão de ramificações estão conectadas.
Para cortar esses ramos e movê-los para outro lugar, você pode cortar cada um deles, para fazer 1 milhão de cortes ou antes do nó, fazendo apenas um corte (essa é a diferença entre mover os arquivos e o diretório).
fonte
mv
no mesmo sistema de arquivos seja apenas uma reescrita da entrada do sumário.mv *.jpg
provavelmente falhará em 12 milhões de arquivos, razão pela qual ele usa o find. A maioria dos Unixes, incluindo o Linux, acredito (a menos que alguém o tenha alterado nos últimos 5 a 10 anos) tenha um comprimento máximo limitado da linha de comando. Eu acho que foi 64K para Linux por um longo tempo. O mesmo limite se aplica a variáveis de ambiente, tenho certeza.Ainda será lento porque, como observado, o sistema de arquivos precisa vincular novamente cada nome de arquivo ao seu novo local.
No entanto, você pode acelerar o que tem agora.
Seu comando find executa o exec uma vez para cada arquivo. Por isso, lança o
mv
comando 12 milhões de vezes para 12 milhões de arquivos. Isso pode ser aprimorado de duas maneiras.Adicione uma vantagem ao final:
find -maxdepth 1 -name '*.jpg' -exec mv -t ../../dst/ +
verifique a página de manual para garantir que ela seja suportada na sua versão do
find
. O efeito deve ser executar uma série demv
comandos com quantos nomes de arquivos caberem em cada linha de comando.Use
find
exargs
juntos.find -maxdepth 1 -name '*.jpg' -print0 | xargs -0 mv -t ../../dst/
Ele
-print0
usará NUL, também conhecido como zero bytes, para separar os nomes dos arquivos. Isso maisxargs -0
corrige todos os problemasxargs
que teriam com espaços nos nomes dos arquivos. Oxargs
comando lerá a lista de nomes de arquivos dofind
comando e executará omv
comando em quantos nomes de arquivos forem adequados.fonte
Sua confusão vem da abstração do sistema de arquivos, que faz você acreditar que uma pasta contém arquivos e outras pastas de maneira semelhante a uma árvore. Na verdade, isso não é verdade: todos os arquivos e diretórios em um sistema de arquivos estão localizados no mesmo nível e identificados com números de algum tipo, dependendo da implementação. Diretórios são apenas arquivos especiais que contêm listas de outros arquivos.
Quando você "move" arquivos dentro de um sistema de arquivos, os arquivos reais não vão a lugar algum. Em vez disso, as listas dentro dos diretórios são atualizadas para refletir a alteração.
mv src ../dst
move uma única entrada da lista de diretório.
para diretório../dst
, para que seja rápido.find -maxdepth 1 -name '*.jpg' -exec mv -t ../../dst/
precisa mover milhões de entradas, por isso é mais lento. Pode ser potencialmente acelerado se você chamarmv
apenas uma vez e não uma vez por arquivo, e omv
próprio comando pode ser otimizado para mover várias entradas de diretório em uma etapa, mas não há como torná-lo tão rápido quanto quando você move um único diretório .fonte
Uma resposta simplificada
mover um arquivo é feito em 3 etapas:
esse processo é o mesmo para um arquivo ou uma pasta.
e, obviamente, fazer isso para 1 arquivo é 100 mais rápido do que fazer para 100 arquivos.
man link
é o add ()man unlink
é o remove ()mv
apenas usa esses dois comandos acima e adiciona uma verificação intermediária para evitar a perda de dados.fonte