Por que mover alguns arquivos em uma pasta demora mais do que mover a pasta inteira?

20

Eu tenho milhões de imagens no meu servidor de nuvem Ubuntu. Quando eu movo uma pasta completa contendo 12 milhões de imagens usando o comando mv , 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?

Isso é o que está acontecendo:

  1. A pasta src tem 12 milhões de imagens e eu movo para a pasta dst usando

    $ mv  src ../dst
    

    Acontece imediatamente

  2. 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?

    
por sankit 01.06.2016 / 08:40

4 respostas

48

TL; DR : não

Para uma quantidade menor de arquivos, você não precisaria de find , mas, mesmo neste caso simplificado e menor, se você apenas

mv *.jpg ../../dst/

levará mais tempo do que mover o diretório inteiro de uma só vez.

Por quê? O objetivo é entender o que o mv faz.

Resumidamente, mv move um número (que identifica um diretório ou um 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 for implementado de tal forma).

Se a origem e o destino estiverem no mesmo sistema de arquivos, não haverá movimento real dos dados, apenas mudará a posição, o ponto em que eles estão anexados.

Então, quando você está no diretório mv um , você está fazendo esta operação uma vez .

Mas quando você move 1 milhão arquivos, você está fazendo essa operação 1 milhão de vezes .

Para dar um exemplo prático, você tem uma árvore com muitos ramos. Em particular, há um nó ao qual 1 milhão de ramificações estão anexadas. Para cortar esses ramos e movê-los para outro lugar, você pode cortar cada um deles, então você faz 1 milhão de cortes, ou corta um pouco antes do nó, fazendo apenas um corte (essa é a diferença entre mover os arquivos e o diretório).

    
por dadexix86 01.06.2016 / 09:15
13

Ele ainda será lento porque, conforme observado, o sistema de arquivos precisa vincular novamente cada nome de arquivo a 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 comando mv 12 milhões de vezes para 12 milhões de arquivos. Isso pode ser melhorado de duas maneiras.

  • Adicione um sinal de adição ao final:
    find -maxdepth 1 -name '*.jpg' -exec mv -t ../../dst/ +
    Verifique a página do manual para verificar se ela é compatível com sua versão de find . O efeito deve ser executar uma série de comandos mv com tantos nomes de arquivos quantos couberem em cada linha de comando.

  • Use find e xargs juntos.
    find -maxdepth 1 -name '*.jpg' -print0 | xargs -0 mv -t ../../dst/
    O -print0 usará NUL, também conhecido como zero bytes, para separar os nomes dos arquivos. Esse mais xargs -0 corrige qualquer problema que xargs teria com espaços em nomes de arquivos. O comando xargs lerá a lista de nomes de arquivos do comando find e executará o comando mv em quantos nomes de arquivos forem adequados.

por Zan Lynx 01.06.2016 / 10:28
7

Sua confusão vem da abstração do sistema de arquivos que faz você acreditar que uma pasta contém arquivos e outras pastas em uma forma de árvore. Isso não é verdade: todos os arquivos e diretórios dentro de 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 nenhum. 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 do diretório . para o diretório ../dst , por isso é rápido.

find -maxdepth 1 -name '*.jpg' -exec mv -t ../../dst/ tem que mover milhões de entradas, por isso é mais lento. Ele pode ser acelerado se você chamar mv apenas uma vez e não uma vez por arquivo, e o comando mv 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.

    
por Dmitry Grigoryev 01.06.2016 / 11:54
4

Uma resposta simplificada

mover um arquivo é feito em três etapas:

  • add () um link para o arquivo na lista de inode da pasta de destino
  • verifique se o link foi adicionado com sucesso
  • remove () o link da lista de inodes da pasta de origem se a verificação acima foi um sucesso.

este processo é o mesmo para um arquivo ou uma pasta.
e, obviamente, fazer isso para um arquivo é 100 mais rápido do que fazê-lo para 100 arquivos.

man link é o add () e man unlink é o remove () e mv apenas usa esses dois comandos acima e adiciona um check-in entre para evitar a perda de dados.

    
por user257256 01.06.2016 / 19:03

Tags