¿Qué sucede cuando se agregan/eliminan archivos en medio de un bucle sh "for f in *"?

¿Qué sucede cuando se agregan/eliminan archivos en medio de un bucle sh "for f in *"?

Encontré un ejemplo de bucle for en línea. Ahora quiero usarlo en mi código pero no estoy seguro de cómo funciona este bucle.

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

Ahora quiero preguntar eso

  1. ¿Busca en search_dir en cada iteración y copia archivos en search_dir en la variable de entrada un archivo en cada iteración?
  2. ¿O tomo una instantánea de todo el contenido de search_dir y luego almaceno esa instantánea en la variable de entrada?
  3. ¿Hay algún cambio en el resultado si alguien inserta algún archivo en search_dir mientras el bucle aún está funcionando?

Respuesta1

Cuando el shell llega a la forinstrucción -, expandirá el valor de $search_diry realizará el cambio global del nombre del archivo para generar una lista de entradas de directorio sobre las que se repetirá. Esto sucede solo una vez, y si las cosas $search_dirdesaparecen o si se agregan nuevos archivos/directorios a ese directorio mientras se ejecuta el bucle, estos cambios no se recogerán.

Si el bucle opera en las entradas del directorio cuyos nombres están en $entry, es posible que desee probar su existencia en el bucle, especialmente si se sabe que el bucle tarda mucho en ejecutarse y hay muchos archivos que están en constante cambio durante mucho tiempo. una razón u otra:

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

Como señala acertadamente Stéphane en los comentarios, se trata de una prueba superflua enmayoríacasos.

Respuesta2

El shell determina completamente la lista de valores a recorrer antes de comenzar a ejecutar el cuerpo del bucle. Eso es:

  1. El shell construye una ruta utilizando el valor de la variable search_dir.
  2. El shell recopila la lista de nombres de archivos en el directorio especificado para crear la lista de coincidencias para el patrón comodín.
  3. El shell ejecuta el cuerpo del bucle, por turno, con cada elemento de la lista de coincidencias.

Puede cambiar el valor de la variable search_diry cambiar el contenido del directorio mientras se ejecuta el bucle. Esto no afectará en qué archivos actúa el bucle.

Si se elimina un archivo mientras el bucle procesa otros archivos, una vez que llegue a ese archivo, ese archivo no existirá. Dependiendo de lo que hagas en el bucle, puede que importe o no. Si hay un proceso simultáneo que puede eliminar archivos, tenga en cuenta que probar si el archivo existe antes de procesarlo realmente no resolverá ese problema, ya queel archivo podría eliminarse entre el momento de la prueba y el momento de comenzar el procesamiento.

Si necesita marcar un archivo como procesado para asegurarse de no procesarlo dos veces, entonces este script debería mover los archivos a otro directorio una vez que los haya procesado. Mover un archivo a otro directorio (en el mismo sistema de archivos) esatómico: o no está hecho todavía o está hecho, no hay un estado intermedio. Pero una vez más, si undiferenteproceso (posiblemente otra instancia de esos scripts) mueve archivos, entonces el bucle a veces afectará a los archivos que se mueven mientras se ejecuta el bucle.

Si desea procesar archivos nuevos a medida que se crean, deberá realizar el bucle nuevamente. Obviamente, los archivos podrían crearse durante la ejecución del bucle, o después de que se hayan procesado todos los archivos anteriores, por lo que el script debería seguir ejecutándose para siempre. Existen herramientas para esperar hasta que se cree un archivo en un directorio. En Linux, la instalación básica para eso esinotificar; Si necesita procesar archivos a medida que se crean, entoncesinotifywaitoincrondebería ayudarte. Recuerde que inotify solo le notifica sobre los archivos creados (o modificados o accedidos según su activador)despuésse inician los comandos basados ​​en inotify; También deberá ocuparse de los archivos existentes anteriormente, y no puede hacerlo simplemente for entry in *; do …; done; inotifywait …porque los archivos se pueden crear durante la ejecución del bucle o incluso mientras inotifywaitse inicia el comando.

información relacionada