Cómo usar inotifywait para ver un directorio para la creación de archivos de una extensión específica

21

He visto esta respuesta .

Debería considerar usar inotifywait, como ejemplo:

inotifywait -m /path -e create -e moved_to |
    while read path action file; do
        echo "The file '$file' appeared in directory '$path' via '$action'"
        # do something with the file
    done

Mi pregunta es que, el script anterior observa un directorio para la creación de archivos de cualquier tipo, pero ¿cómo modifico el inotifywaitcomando para informar solo cuando se crea un archivo de cierto tipo / extensión (o se mueve al directorio)? informar cuando .xmlse crea cualquier archivo.

Lo que intenté:

Ejecuté el inotifywait --helpcomando y leí las opciones de la línea de comando. Tiene --exclude <pattern>y --excludei <pattern>comandos para EXCLUIR archivos de ciertos tipos (mediante el uso de regEx), pero necesito una forma de INCLUIR solo los archivos de cierto tipo / extensión.

Tímido
fuente
Por cierto, el uso de patharriba probablemente no sea el mejor nombre de variable si quieres jugar con esto primero en un shell. Si lo usa, no podrá usar comandos y todo, ya que esto básicamente ha anulado el estándar PATH. Por lo tanto, recomiendo usar un nombre var alternativo, como en su fpathlugar. es decir while read fpath action file, cualquier comando estándar generalmente disponible desde su shell seguirá siéndolo.
Baptiste Mathus
Es un poco ridículo que no haya una opción de inclusión.
erandros

Respuestas:

17

¿Cómo modifico el comando inotifywait para informar solo cuando se crea un archivo de cierto tipo / extensión?

Tenga en cuenta que este es un código no probado ya que no tengo acceso en inotifyeste momento. Pero algo similar a esto debería funcionar:

inotifywait -m /path -e create -e moved_to |
    while read path action file; do
        if [[ "$file" =~ .*xml$ ]]; then # Does the file end with .xml?
            echo "xml file" # If so, do your thing here!
        fi
    done
maulinglawns
fuente
2
Esto funciona y lo he probado con inotifywait.
TheBetterJORT
1
¿Cómo ejecutas esto? ¿Es un comando de una sola vez o necesita ejecutarse en un bucle o algo así? Quizás como parte de incron(espero que no).
SDsolar
@SDsolar Varía. Para mí, que generalmente se ejecuta inotify, ya sea con nohupo empezar con el servicio systemd una costumbre. Muy a menudo este último.
maulinglawns
9

Use un doble negativo:

inotifywait -m --exclude "[^j][^s]$" /path -e create -e moved_to |
    while read path action file; do
        echo "The file '$file' appeared in directory '$path' via '$action'"
    done

Esto solo incluirá archivos javascript

Jonas Earendel
fuente
1
Agradable, me gusta que cambie el filtrado para inotifywaitque genere una gran salida para todos los archivos y luego los filtre (como en la otra respuesta). No lo he intentado, pero supongo que funcionaría un poco más rápido.
TMG
Esto es justo lo que estaba buscando. Cómo modificar la --excludeentrada para ver los .extarchivos. ¿Esto se ejecuta solo una vez o en un bucle for?
kurokirasama
Es un demonio, por lo que se ejecutará hasta que se bloquee o lo
apagues
Lo siento, perdí la primera pregunta. inotifywait -m --exclude "[^.][^e][^x][^t]$" /home/jonas/Skrivbord/test -e create -e moved_to | while read path action file; do echo "The file '$file' appeared in directory '$path' via '$action'" done Estoy seguro de que la expresión regular se puede optimizar, pero este bebé funciona :)
Jonas Earendel
Gracias !! ¡¡Voy a tratar de salir!!
kurokirasama
3

Mientras que el enfoque doble negativo de la respuesta anterior es una buena idea, ya que (como señaló TMG) ​​realmente cambia el trabajo de filtrado inotifywait, no es correcto.

Por ejemplo, si un archivo termina as, no coincidirá [^j][^s]$porque la letra finals no coincide [^s], por lo tanto, no se excluirá.

En términos booleanos, si Ses la declaración:

"la carta final es s"

y Jes la declaración:

"la penúltima letra es j"

entonces el valor del --excludeparámetro debería igualar semánticamente a lo not(J and S)que, según las leyes de De Morgan, es not(J) or not(S).

Otro problema potencial es que zsh, en , $pathes una variable incorporada que representa el equivalente de la matriz $PATH, por lo que la while read path ...línea se desordenará completamente $PATHy hará que todo se vuelva ejecutable desde el shell.

Por lo tanto, el enfoque correcto es:

inotifywait -m --exclude "[^j].$|[^s]$" /path -e create -e moved_to |
    while read dir action file; do
        echo "The file '$file' appeared in directory '$dir' via '$action'"
    done

Tenga en cuenta lo .que se necesita después [^j]para asegurarse de que la coincidencia se aplique en la penúltima posición, y también que el |carácter (que representa el OR booleano mencionado anteriormente) no se debe escapar aquí porque --excludetoma expresiones regulares extendidas POSIX.

Adam Spires
fuente