mv
dentro do mesmo sistema de arquivos é atômico para cada arquivo, mas no sistema de arquivos é uma operação muito mais complexa (supondo que você esteja apenas movendo arquivos regulares e que os destinos não existam inicialmente):
- Remova o arquivo de destino, se existir.
- Abra o arquivo de origem para leitura. Algumas implementações podem executar isso antes da etapa anterior.
- Crie o arquivo de destino. Algumas implementações podem truncá-lo se existir nesse ponto. Algumas implementações podem executar isso antes da etapa anterior.
- Leia alguns dados do arquivo de origem e grave-os no arquivo de destino.
- Replique os metadados do arquivo de origem no arquivo de destino. Algumas implementações podem executar parte ou tudo isso após a próxima etapa.
- Feche o arquivo de origem e o arquivo de destino.
- Remova o arquivo de origem.
Na maior parte, se dois processos mv
tentarem mover o mesmo arquivo ao mesmo tempo, ambos copiarão os dados: a primeira instância a iniciar criará um arquivo, a segunda instância excluirá esse arquivo e crie um novo. No entanto, se você tiver azar, é possível perder dados. Por exemplo:
- A instância 1 executa a cópia e fecha os dois arquivos (etapas 1 a 6).
- Nesse ponto, a instância 2 alcança esse arquivo e remove o destino (etapa 1), mas fica impedida antes de poder abrir o arquivo de origem.
- A instância 1 prossegue para remover o arquivo de origem (etapa 7).
- A instância 2 vai para a etapa 2, mas o arquivo não existe mais.
Acho que, se um arquivo estiver presente no destino, ele terá o conteúdo correto. Mas, como vimos, é possível que um arquivo desapareça.