Verwendung von inotifywait zum Überwachen eines Verzeichnisses zum Erstellen von Dateien mit einer bestimmten Erweiterung

21

Ich habe diese Antwort gesehen .

Sie sollten in Betracht ziehen, inotifywait als Beispiel zu verwenden:

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

Meine Frage ist, dass das obige Skript ein Verzeichnis für die Erstellung von Dateien eines beliebigen Typs überwacht, aber wie ändere ich den inotifywaitBefehl, um nur zu melden, wenn eine Datei eines bestimmten Typs / einer bestimmten Erweiterung erstellt (oder in das Verzeichnis verschoben) wird - z. B. sollte es melden, wenn eine .xmlDatei erstellt wird.

WAS ICH VERSUCHT HABE:

Ich habe den inotifywait --helpBefehl ausgeführt und die Befehlszeilenoptionen gelesen. Es hat --exclude <pattern>und --excludei <pattern>Befehle zum EXCLUDE von Dateien bestimmter Typen (mit regEx), aber ich brauche eine Möglichkeit, nur die Dateien eines bestimmten Typs / einer bestimmten Erweiterung zu INCLUDE .

Schüchtern
quelle
Übrigens ist die Verwendung der pathobigen Option wahrscheinlich nicht der beste Variablenname, wenn Sie zuerst in einer Shell damit spielen möchten. Wenn Sie es verwenden, können Sie nicht alle Befehle verwenden, da dies im Grunde genommen nur den Standard überschrieben hat PATH. Daher empfehle ich, stattdessen einen alternativen Variablennamen zu fpathverwenden. Das heißt, while read fpath action filejeder Standardbefehl, der normalerweise in Ihrer Shell verfügbar ist, ist weiterhin verfügbar.
Baptiste Mathus
Es ist irgendwie lächerlich, dass es keine Include-Option gibt.
Erandros

Antworten:

17

Wie ändere ich den Befehl inotifywait, um nur zu melden, wenn eine Datei eines bestimmten Typs / einer bestimmten Erweiterung erstellt wird?

Bitte beachten Sie, dass dies nicht getesteter Code ist, da ich momentan keinen Zugriff darauf habe inotify. Aber so etwas sollte funktionieren:

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
quelle
2
Das funktioniert und ich habe es mit inotifywait getestet.
TheBetterJORT
1
Wie läuft das ab? Handelt es sich um einen einmaligen Befehl, oder muss er in einer Schleife oder ähnlichem ausgeführt werden? Vielleicht im Rahmen von incron(hoffe ich nicht).
SDsolar
@ SDsolar Es variiert. Normalerweise starte ich das Programm inotifyentweder nohupmit einem benutzerdefinierten systemd-Dienst. Meistens letzteres.
Maultinglawns
9

Verwenden Sie ein doppeltes Negativ:

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

Dies wird nur Javascript-Dateien enthalten

Jonas Earendel
quelle
1
Schön, ich mag es, dass es die Filterung verschiebt, inotifywaitanstatt eine riesige Ausgabe für alle Dateien zu generieren und danach zu filtern (wie in der anderen Antwort). Ich habe es nicht versucht, aber ich denke, das würde etwas schneller gehen.
TMG
Das ist genau das, wonach ich gesucht habe. So ändern Sie die --excludeEingabe, um nach .extDateien zu suchen. Dies wird nur einmal ausgeführt oder in einer for-Schleife?
Kurokirasama
Es ist ein Daemon, also läuft es, bis es abstürzt oder Sie es herunterfahren :)
Jonas Earendel
Entschuldigung, habe die erste Frage verpasst. 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 Ich bin sicher, dass der reguläre Ausdruck optimiert werden kann, aber dieses Baby funktioniert :)
Jonas Earendel
Danke !! Ich werde es ausprobieren!!
Kurokirasama
3

Der doppelt negative Ansatz der vorherigen Antwort ist zwar eine gute Idee, da er (wie TMG feststellte) tatsächlich die Filteraufgabe verschiebt inotifywait, aber nicht korrekt ist.

Wenn beispielsweise eine Datei endet in asdann wird es nicht passen , [^j][^s]$weil der letzte Buchstabe snicht übereinstimmt [^s], wird daher nicht ausgeschlossen werden.

In Booleschen Begriffen Slautet die folgende Aussage:

"Der letzte Buchstabe ist s"

und Jist die Aussage:

"Der vorletzte Buchstabe ist j"

dann sollte der Wert des --excludeParameters semantisch gleich sein not(J and S), wie es nach De Morgans Gesetzen ist not(J) or not(S).

Ein weiteres mögliches Problem ist, dass in zsh, $patheine eingebaute Variable ist, die das Array-Äquivalent von darstellt $PATH, sodass die while read path ...Zeile völlig durcheinander $PATHgerät und alles von der Shell aus nicht mehr ausführbar ist.

Daher ist der richtige Ansatz:

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

Beachten Sie das, .was danach benötigt wird, [^j]um sicherzustellen, dass die Übereinstimmung in der vorletzten Position angewendet wird und dass das |Zeichen (das das oben erwähnte boolesche ODER darstellt) hier nicht maskiert werden sollte, da --excludeerweiterte reguläre POSIX-Ausdrücke verwendet werden.

Adam Spires
quelle