O que acontece quando arquivos são adicionados/removidos no meio de um loop sh "for f in *"?

O que acontece quando arquivos são adicionados/removidos no meio de um loop sh "for f in *"?

Encontrei um exemplo de loop for online. Agora quero usá-lo em meu código, mas não tenho certeza de como esse loop funciona

for entry in "$search_dir"/* 
do
  echo "$entry"
done

Agora eu quero perguntar isso

  1. Ele procura em search_dir em cada iteração e copia os arquivos em search_dir para a variável de entrada um arquivo em cada iteração?
  2. Ou tiro um instantâneo de todo o conteúdo de search_dir e depois armazeno esse instantâneo na variável de entrada?
  3. Existe alguma alteração na saída se alguém inserir algum arquivo em search_dir enquanto o loop ainda estiver funcionando?

Responder1

Quando o shell chegar à forinstrução -, ele expandirá o valor $search_dire executará o globbing do nome do arquivo para gerar uma lista de entradas de diretório que serão iteradas. Isso acontece apenas uma vez, e se as coisas desaparecerem $search_dirou se houver novos arquivos/diretórios adicionados a esse diretório enquanto o loop estiver em execução, essas alterações não serão detectadas.

Se o loop operar nas entradas do diretório cujos nomes estão em $entry, pode-se querer testar sua existência no loop, especialmente se o loop leva muito tempo para ser executado e há muitos arquivos que estão em fluxo constante por uma razão ou outra:

for entry in "$search_dir"/*; do
    if [ -e "$entry" ]; then
        # operate on "$entry"
    else
        # handle the case that "$entry" went away
    fi
done

Como Stéphane acertadamente salienta nos comentários, este é um teste supérfluo paramaioriacasos.

Responder2

O shell determina completamente a lista de valores para fazer o loop antes de iniciar a execução do corpo do loop. Aquilo é:

  1. O shell constrói um caminho usando o valor da variável search_dir.
  2. O shell coleta a lista de nomes de arquivos no diretório especificado para construir a lista de correspondências para o padrão curinga.
  3. O shell executa o corpo do loop, por sua vez, com cada elemento da lista de correspondências.

Você pode alterar o valor da variável search_dire alterar o conteúdo do diretório enquanto o loop está em execução. Isso não afetará em quais arquivos o loop atua.

Se um arquivo for removido enquanto o loop estiver processando outros arquivos, quando chegar a esse arquivo, esse arquivo não existirá. Dependendo do que você faz no loop, isso pode ou não importar. Se houver um processo simultâneo que possa remover arquivos, observe que testar se o arquivo existe antes de processá-lo não resolverá realmente o problema, poiso arquivo pode ser removido entre o momento do teste e o início do processamento.

Se você precisar marcar um arquivo como processado para garantir que não o processe duas vezes, esse script deverá mover os arquivos para outro diretório depois de processá-los. Mover um arquivo para outro diretório (no mesmo sistema de arquivos) éatômico: ou ainda não está feito ou está feito, não há estado intermediário. Mas mais uma vez, se umdiferenteprocesso (possivelmente outra instância desses scripts) move arquivos, então o loop às vezes atingirá arquivos que são movidos enquanto o loop está em execução.

Se quiser processar novos arquivos à medida que eles são criados, você precisará fazer um loop novamente. Obviamente, os arquivos podem ser criados durante a execução do loop ou após todos os arquivos anteriores terem sido processados, portanto o script precisaria continuar em execução para sempre. Existem ferramentas para esperar até que um arquivo seja criado em um diretório. No Linux, o recurso básico para isso énotificar; se você precisar processar arquivos à medida que eles são criados, entãoinotifywaitouíncrondeveria ajudá-lo. Lembre-se que o inotify apenas notifica sobre arquivos criados (ou modificados ou acessados ​​dependendo do seu gatilho)depoisos comandos baseados em inotify são iniciados; você também precisará cuidar dos arquivos existentes anteriormente, e não pode fazer isso simplesmente for entry in *; do …; done; inotifywait …porque os arquivos podem ser criados durante a execução do loop ou mesmo enquanto o inotifywaitcomando está sendo inicializado.

informação relacionada