Vários comandos mv podem ser executados no mesmo diretório (condição de corrida)?

4

Estou movendo um grande número de arquivos (400K +) de um diretório para outro e tenho o seguinte script para fazer isso (muitos arquivos para o comando mv trabalhar diretamente):

for file in *;
do
    mv $file ..
done

Se eu executar este script duas vezes (ou mais) ao mesmo tempo, haverá uma condição de corrida quando / se os comandos mv estiverem tentando acessar o mesmo arquivo?

Eu procurei na web, mas não encontrei nenhuma resposta definitiva. Obrigado!

    
por D. Gibbs 06.11.2014 / 05:09

2 respostas

5

Existe de fato uma condição de corrida (uma que não causaria danos, no entanto).

O * é expandido na entrada do loop. Se você executar uma segunda instância desse script simultaneamente, provavelmente não fará nada porque todos os arquivos que ele tenta mover já foram movidos. Se nenhum arquivo for criado no diretório de origem durante a operação de movimentação, as mensagens de erro deverão ser seu maior problema.

Mas, em geral, essa estrutura é uma ideia muito ruim. * se expande para uma lista classificada. AFAIK não é possível desativar isso. Obviamente, a classificação sozinha é um pesadelo com 400 mil arquivos. Veja man bash , seção "Expansão do nome do caminho":

After word splitting, unless the -f option has been set, bash scans each word for the characters *, ?, and [. If one of these characters appears, then the word is regarded as a pattern, and replaced with an alphabetically sorted list of file names matching the pattern.

Além disso, você não deve executar uma mv instância por arquivo, pois pode mover vários arquivos de uma só vez.

Esta é uma solução melhor (no mundo GNU):

find . -mindepth 1 -maxdepth 1 -exec mv --target-directory=DIRECTORY {} +
    
por 06.11.2014 / 05:30
3

Uma solução ainda melhor seria usar GNU Parallel para insert multiple arguments . Por padrão, o Parallel executará n jobs simultaneamente, com n sendo o número de núcleos que sua CPU possui.

Ao mover muitos arquivos como este: mv * destdir às vezes você receberá o erro:

bash: /bin/mv: Argument list too long

porque há muitos arquivos. Você pode fazer:

ls -1 | parallel mv {} destdir

Isso executará mv para cada arquivo. Isso pode ser feito mais rápido se o mv obtiver tantos argumentos que caberão na linha:

ls -1 | parallel -m mv {} destdir


A opção -m é realmente legal para mover ou copiar arquivos em paralelo:

-m      Multiple arguments. Insert as many arguments as the command
        line length permits. If multiple jobs are being run in
        parallel: distribute the arguments evenly among the jobs.
        Use -j1 to avoid this.
    
por 17.11.2014 / 00:34

Tags