Comment utiliser inotifywait pour surveiller un répertoire pour la création de fichiers d'une extension spécifique

21

J'ai vu cette réponse .

Vous devriez envisager d'utiliser inotifywait, par exemple:

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

Ma question est que, le script ci-dessus surveille un répertoire pour la création de fichiers de tout type, mais comment puis-je modifier la inotifywaitcommande pour signaler uniquement lorsqu'un fichier d'un certain type / extension est créé (ou déplacé dans le répertoire) - par exemple, il devrait signaler lorsqu'un .xmlfichier est créé.

CE QUE J'AI ESSAYÉ:

J'ai exécuté la inotifywait --helpcommande et j'ai lu les options de ligne de commande. Il a --exclude <pattern>et des --excludei <pattern>commandes pour EXCLURE les fichiers de certains types (en utilisant regEx), mais j'ai besoin d'un moyen pour INCLURE uniquement les fichiers d'un certain type / extension.

Timide
la source
BTW, l'utilisation pathci-dessus n'est probablement pas le meilleur nom de variable si vous voulez jouer avec cette première dans un shell. Si vous l'utilisez, vous ne pourrez pas utiliser les commandes et tout, car cela vient de remplacer la norme PATH. Par conséquent, je recommande d'utiliser un autre nom de var, comme à la fpathplace. c'est-à-dire que while read fpath action filetoute commande standard habituellement disponible à partir de votre shell le sera toujours.
Baptiste Mathus
c'est un peu ridicule qu'il n'y ait pas d'option include.
erandros

Réponses:

17

comment puis-je modifier la commande inotifywait pour signaler uniquement lorsqu'un fichier d'un certain type / extension est créé

Veuillez noter qu'il s'agit d'un code non testé car je n'y ai pas accès pour inotifyle moment. Mais quelque chose de semblable devrait fonctionner:

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
la source
2
Cela fonctionne et je l'ai testé avec inotifywait.
TheBetterJORT
1
Comment gérez-vous cela? Est-ce une commande unique ou doit-elle être exécutée en boucle ou quelque chose comme ça? Peut-être dans le cadre de incron(j'espère que non).
SDsolar
@SDsolar Cela varie. Pour moi, je l'exécute généralement inotifyavec nohupou le démarre avec un service systemd personnalisé. Le plus souvent, ce dernier.
maulinglawns
9

Utilisez un double négatif:

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

Cela inclura uniquement les fichiers javascript

Jonas Earendel
la source
1
Bien, j'aime que cela déplace le filtrage inotifywaitplutôt que de générer une énorme sortie pour tous les fichiers et de filtrer ensuite (comme dans l'autre réponse). Je n'ai pas essayé, mais je suppose que cela fonctionnerait un peu plus vite.
TMG
C'est exactement ce que je cherchais. Comment modifier l' --excludeentrée pour surveiller les .extfichiers. Ceci est exécuté une seule fois ou dans une boucle for?
kurokirasama
C'est un démon, donc il fonctionnera jusqu'à ce qu'il se bloque ou que vous l'éteigniez :)
Jonas Earendel
Désolé, j'ai raté la première question. 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 Je suis sûr que l'expression régulière peut être optimisée, mais ce bébé fonctionne :)
Jonas Earendel
Merci !! Je vais l'essayer!!
kurokirasama
3

Bien que l'approche à double négatif de la réponse précédente soit une bonne idée car (comme l'a noté TMG), elle transfère effectivement le travail de filtrage vers inotifywait, elle n'est pas correcte.

Par exemple, si un fichier se termine, asil ne correspondra pas [^j][^s]$car la lettre finale sne correspond pas [^s], il ne sera donc pas exclu.

En termes booléens, if Sest la déclaration:

"la dernière lettre est s"

et Jest la déclaration:

"l'avant-dernière lettre est j"

la valeur du --excludeparamètre doit correspondre à sémantiquement not(J and S), qui , par les lois de De Morgan est not(J) or not(S).

Un autre problème potentiel est que dans zsh, $pathest une variable intégrée représentant l'équivalent du tableau de $PATH, de sorte que la while read path ...ligne sera complètement gâchée $PATHet que tout deviendra inexécutable à partir du shell.

Par conséquent, la bonne approche est la suivante:

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

Notez ce .qui est nécessaire après [^j]pour s'assurer que la correspondance est appliquée dans l'avant-dernière position, et aussi que le |caractère (représentant le booléen OU mentionné ci-dessus) ne doit pas être échappé ici car --excludeprend des expressions régulières étendues POSIX.

Adam Spires
la source