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

5

Eu encontrei um exemplo de loop on-line. Agora eu quero usá-lo no meu código, mas não tenho certeza de como esse loop opera

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

Agora quero perguntar que

  1. Parece 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 eu faço um instantâneo de todo o conteúdo de search_dir e, em seguida, armazeno esse instantâneo na variável de entrada?
  3. Há alguma mudança na saída se alguém inserir algum arquivo no search_dir enquanto o loop ainda estiver funcionando?
por ProgBeginner 25.04.2017 / 15:20

2 respostas

5

Quando o shell chegar à for -statement, ele expandirá o valor de $search_dir e executará o nome do arquivo globbing para gerar uma lista de entradas de diretório que serão iteradas. Isso acontece apenas uma vez, e se as coisas em $search_dir desaparecerem ou 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 selecionadas.

Se o loop operar nas entradas de diretório cujos nomes estão em $entry , pode-se testar sua existência no loop, especialmente se o loop demorar muito para ser executado e houver muitos arquivos que estão em constante fluxo 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 aponta corretamente nos comentários, este é um teste supérfluo nos mais casos.

    
por 25.04.2017 / 15:29
1

O shell determina completamente a lista de valores a serem ativados antes de começar a executar o corpo do loop. Isso é:

  1. O shell cria 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 criar 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_dir e alterar o conteúdo do diretório enquanto o loop está em execução. Isso não afetará quais arquivos o loop atua.

Se um arquivo for removido enquanto o loop estiver processando outros arquivos, uma vez que ele chegue ao arquivo, esse arquivo não existirá. Dependendo do que você faz no loop, pode ou não importar. Se houver um processo concorrente que possa remover arquivos, observe que testar se o arquivo existe antes de processá-lo não resolverá realmente esse problema, uma vez que o arquivo pode ser removido entre o tempo de teste e a hora em que você começa a processar .

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

Se você quiser processar novos arquivos à medida que eles são criados, você precisará fazer um loop novamente. Obviamente, 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 funcionando para sempre. Existem ferramentas para esperar até que um arquivo seja criado em um diretório. No Linux, o recurso básico para isso é inotify ; Se você precisar processar os arquivos à medida que eles são criados, inotifywait ou incron deve ajudá-lo. Lembre-se que o inotify só notifica você sobre arquivos criados (ou modificados ou acessados dependendo do seu trigger) após os comandos baseados em inotify iniciarem; você também precisará cuidar dos arquivos anteriores existentes, e você não pode fazer apenas for entry in *; do …; done; inotifywait … porque os arquivos podem ser criados durante a execução do loop ou até mesmo quando o comando inotifywait estiver sendo inicializado.

    
por 26.04.2017 / 02:41