Wie erkenne ich neue Dateien in einem Ordner mit einem Bash- Skript? Ich möchte die Dateien bearbeiten, sobald sie im Ordner angelegt sind. Ist dies möglich oder muss ich ein Skript mit cron planen, das jede Minute nach neuen Dateien sucht?
Wie erkenne ich neue Dateien in einem Ordner mit einem Bash- Skript? Ich möchte die Dateien bearbeiten, sobald sie im Ordner angelegt sind. Ist dies möglich oder muss ich ein Skript mit cron planen, das jede Minute nach neuen Dateien sucht?
Antworten:
Sie sollten als inotifywait
Beispiel in Betracht ziehen :
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
In Ubuntu inotifywait
ist das inotify-tools
Paket vorgesehen. Ab Version 3.13 (aktuell in Ubuntu 12.04) inotifywait
wird der Dateiname ohne die Option -f angegeben. Ältere Versionen müssen möglicherweise erzwungen werden. Was wichtig ist, ist, dass die -e
Option to inotifywait
die beste Methode zum Filtern von Ereignissen ist. Außerdem kann Ihr read
Befehl die Positionsausgabe mehreren Variablen zuweisen, die Sie verwenden oder ignorieren können. Es ist nicht erforderlich, grep / sed / awk zu verwenden, um die Ausgabe vorzuverarbeiten.
inotifywait
war genau das, was ich wollte.
The '--filename' option no longer exists. The option it enabled in earlier versions of inotifywait is now turned on by default.
Also, müssen Sie nur tun, inotifywait -m /path -e create |
ich werde versuchen, diese Antwort zu bearbeiten.
fswatch
. Ich habe es nicht geschrieben, aber es ist Open Source und ich benutze es.
Ich bevorzuge incron
, da es einfacher zu handhaben ist. Im Wesentlichen handelt es sich um einen Dienst, inotify
mit dem Sie Konfigurationen einrichten können, um basierend auf Dateiänderungsvorgängen Maßnahmen zu ergreifen.
Ex:
<directory> <file change mask> <command or action> options
/var/www/html IN_CREATE /root/scripts/backup.sh
Ein vollständiges Beispiel finden Sie hier: http://www.cyberciti.biz/faq/linux-inotify-examples-to-replicate-directories/
Ich habe das gerade ausgedacht und sehe keine großen Probleme damit, abgesehen von einer winzigen Chance, dass Dateien zwischen Überprüfungen fehlen.
while true
do
touch ./lastwatch
sleep 10
find /YOUR/WATCH/PATH -cnewer ./lastwatch -exec SOMECOMMAND {} \;
done
Wenn Ihre Dateiverarbeitung nicht zu lange dauert, sollten Sie keine neue Datei verpassen. Sie könnten auch Hintergrundinformationen zu den Aktivitäten anzeigen ... Es ist nicht kugelsicher, dient jedoch einigen Zwecken ohne externe Tools wie inotify.
inotify
nicht verfügbar. Ich würde nur hinzufügen -type f
, um Dateien herauszufiltern. Andernfalls wird der Ordner ebenfalls zurückgegeben.
-f filename
Option ist großartig. Dann bleibt nur noch die Frage, wie dies beim Neustart gestartet werden kann. Ich werde dies mit meiner Solaranlage verwenden, os.system("ssh me@mysystem ' ( touch /home/me/alarms/low24 ) '")
damit der Mastercomputer beim Erstellen dieser Datei espeak
die Niederspannung verwendet und ankündigt. Es sendet mir bereits eine E-Mail, aber da mein System die Uhrzeit bereits zur vollen Stunde anzeigt, hat es den Rest. askubuntu.com/questions/977613/…
Sie können watch
in Ihrem Skript verwenden
watch -n 0.1 ls <your_folder>
Überwacht Ihren Ordner und listet Sie alle 0,1 Sekunden auf
Nachteil
Ist nicht in Echtzeit, wenn also eine Datei in weniger als 0,1 Sekunden erstellt und gelöscht wurde, dann würde dies nicht funktionieren, watch
unterstützt nur mindestens 0,1 Sekunden.
Ich gehe davon aus, dass der Zielordner (der Einfachheit halber nenne ich ihn isempty
) leer ist und Sie darauf warten, dass eine oder mehrere Dateien dort abgelegt werden.
Sie können den folgenden Befehl verwenden:
ls -1A isempty | wc -l
Nur um zu überprüfen, ob der Ordner noch leer ist, wird eine 0 zurückgegeben, wenn keine neue Datei vorhanden ist (daher ist der isempty
Ordner noch leer), oder es wird ein Wert größer als 0 zurückgegeben (tatsächlich die Nummer) Dateien im Ordner).
Das sagte ein dummer Wenn / Dann-Test kann den Rest der Arbeit machen:
if [ $(ls -1A isempty | wc -l) -gt 0 ] ; then do_something ; fi
Natürlich muss die do_something
Funktion die Datei (en) innerhalb des isempty
Ordners manipulieren und sie dann nach der Verarbeitung aus dem Ordner selbst entfernen.
Wenn Sie eine Zeile wie die folgende in Ihre crontab einfügen, wird die Prüfung einmal pro Minute ausgeführt und die do_something
Aktion ausgelöst, wenn der Ordner natürlich nicht leer ist:
* * * * * if [ $(ls -1A isempty | wc -l) -gt 0 ] ; then do_something ; fi
Wenn Sie neue Dateien erkennen möchten, verarbeiten Sie diese und löschen Sie am Ende die verarbeiteten Dateien. Verwenden Sie dazu die Datei systemd.path . Diese Methode basiert auf inotify. Es gibt eine Option DirectoryNotEmpty, damit systemd Ihr Skript immer dann ausführen kann, wenn Dateien im Verzeichnis erkannt werden. Sie müssen sich daran erinnern, dass es nur funktioniert, wenn Sie verarbeitete Dateien löschen können und das Skript das Verzeichnis leer lässt.
Bereiten Sie zuerst die Datei mymonitor.service vor
[Unit]
Description=Start the script
[Service]
Type=oneshot
ExecStart=/path/to/your/script
Als nächstes gehen Sie zu mymonitor.path, um den Pfad zu definieren
[Unit]
Description= Triggers the service
[Path]
DirectoryNotEmpty=/path/to/monitor
[Install]
WantedBy=multi-user.target
Wenn der Name der .path-Datei mit dem Namen des Dienstes identisch ist, muss der Dienstname nicht in der .path-Datei angegeben werden.
Es basiert auf der Überwachung des Dateizugriffs auf Dummies
entr
Verwenden entr
ist der neue Weg, dies zu tun (es ist plattformübergreifend). Beachten Sie, entr
dass Polling nicht verwendet wird, um einen großen Vorteil gegenüber vielen Alternativen zu erzielen.
Verwendet
kqueue(2)
oderinotify(7)
um Umfragen zu vermeiden.entr
wurde geschrieben, um schnelle Rückmeldungen und automatisierte Tests natürlich und völlig normal zu machen.
Auf BSD verwendet pledge(2)
Sie können es mit installieren
apt-get install entr
dnf install entr
Sie können ein Verzeichnis für neue Ergänzungen mit verfolgen
while $(true); do
# echo ./my_watch_dir | entr -dnr echo "Running trigger..."
echo ./my_watch_dir | entr -dnr ##MY COMMAND##
done;
Optionen erklärt (aus den Dokumenten),
-d
Verfolgen Sie die Verzeichnisse der regulären Dateien, die als Eingabe bereitgestellt werden, und beenden Sie sie, wenn eine neue Datei hinzugefügt wird. Mit dieser Option können auch Verzeichnisse explizit angegeben werden. Dateien mit Namen, die mit '.' Beginnen werden ignoriert.-n
Im nicht interaktiven Modus ausführen. In diesem Modus versucht entr nicht, aus dem TTY zu lesen oder seine Eigenschaften zu ändern.-r
Laden Sie einen persistenten untergeordneten Prozess neu. Wie bei der Standardbetriebsart wird ein Dienstprogramm, das beendet wird, erst dann erneut ausgeführt, wenn ein Dateisystem- oder Tastaturereignis verarbeitet wird.SIGTERM
wird verwendet, um das Dienstprogramm vor dem Neustart zu beenden. Eine Prozessgruppe wird erstellt, um zu verhindern, dass Shell-Skripte Signale maskieren.entr
Wartet auf das Beenden des Dienstprogramms, um sicherzustellen, dass Ressourcen wie Sockets geschlossen wurden. Die Steuerung des TTY wird nicht auf den Kindprozess übertragen.
Bash kann das nicht einfach. Sie müssten im Grunde genommen eine Liste aller Dateien im Ordner erstellen, regelmäßig eine neue Liste erstellen und diese vergleichen, um festzustellen, was sich geändert hat.
Was Sie suchen, heißt inotify. Es ist in den Linux-Kernel integriert und Sie können im Grunde dort sitzen und warten, bis etwas passiert. Dann kommt inotify zurück und sagt: "Hey, es gibt eine neue Datei namens foobar."
Um das zu erreichen, was Sie wollen, müssen Sie zu etwas wie Perl wechseln und Linux :: Inotify2 verwenden (Python unterstützt wahrscheinlich auch Inotify, aber ich bin eine Perl-Person).
Dies funktioniert unter Cygwin und Linux. Einige der vorherigen Lösungen, die eine Datei schreiben, führen zu einem Thrash der Festplatte. Dieses Skript hat dieses Problem nicht:
SIG=1
SIG0=$SIG
while [ $SIG != 0 ] ; do
while [ $SIG = $SIG0 ] ; do
SIG=`ls -1 | md5sum | cut -c1-32`
sleep 10
done
SIG0=$SIG
ls -lrt | tail -n 1
done
Unten finden Sie eine gekürzte Version eines Beispiels für Stackoverflow , das ich getestet und in eines meiner Projekte integriert habe und das die Überwachung bestimmter Verzeichnisse erfordert.
Var_dir="${1:-/tmp}"
Var_diff_sleep="${2:-120}"
Var_diff_opts="--suppress-common-lines"
Func_parse_diff(){
_added="$(grep -E '>' <<<"${@}")"
if [ "${#_added}" != "0" ]; then
mapfile -t _added_list <<<"${_added//> /}"
_let _index=0
until [ "${#_added_list[@]}" = "${_index}" ]; do
_path_to_check="${Var_dir}/${_added_list[${_index}]}"
if [ -f "${_path_to_check}" ]; then
echo "# File: ${_path_to_check}"
elif [ -d "${_path_to_check}" ]; then
echo "# Directory: ${_path_to_check}"
if [ -p "${_path_to_check}" ]; then
echo "# Pipe: ${_path_to_check}"
fi
let _index++
done
unset _index
fi
}
Func_watch_bulk_dir(){
_current_listing=""
while [ -d "${Var_dir}" ]; do
_new_listing="$(ls "${Var_dir}")"
_diff_listing="$(diff ${Var_dec_diff_opts} <(${Var_echo} "${_current_listing}") <(${Var_echo} "${_new_listing}"))"
if [ "${_diff_listing}" != "0" ]; then
Func_parse_diff "${_diff_listing}"
fi
_current_listing="${_new_listing}"
sleep ${Var_diff_sleep}
done
}
Hier ist ein Link zu einem Skript , das eine geänderte Version von oben verwendet, um Dateien oder Verzeichnisse, die sich im sshfs-Mountpunkt befinden, automatisch zu entschlüsseln. das vorgenannte Projekt.