Inotifywait one-liner
Ceci utilise inotifywait tout en évitant l'utilisation de while read -r
:
inotifywait -q --format '%f' -e close_write,moved_to -m . |
grep --line-buffered -F -x 'myfile.py' |
xargs -l -i './myfile.py'
Explication : inotifywait
édite une ligne avec le nom du fichier lorsqu'il détecte un changement, grep
filtre le nom du fichier ciblé, et xargs
exécute une commande pour chaque nom de fichier.
inotifywait
paramètres :
-
-q
: Supprimer les messages stderr.
-
--format '%f'
N'affiche que le nom du fichier, nous ne filtrons pas les événements de toute façon.
-
-e close_write,moved_to
Ne détecte que close_write (le fichier a été écrit), et moved_to (la plupart des éditeurs utilisent des fichiers d'échange, et déplacent la mémoire tampon vers le fichier lors de l'enregistrement).
-
-m
Continuer à écouter indéfiniment (appuyer sur CTRL+C pour interrompre).
-
.
Répertoire cible qui contient le fichier ciblé.
grep
paramètres :
-
--line-buffered
: Vider les lignes immédiatement, traiter comme un flux (comme sed
).
-
-F
: Nom de fichier littéral, n'analyse pas l'expression régulière (sinon il faudrait échapper le point) : myfile\.py
).
-
-x
: Correspondre à la ligne entière, et pas seulement à une sous-chaîne du nom de fichier.
xargs
paramètres :
-
-l
: Exécuter pour chaque ligne d'entrée, ne pas regrouper les lignes.
-
-i
: Empêcher le nom de fichier d'être ajouté comme argument à la commande, il remplace {}
dans la commande avec la ligne d'entrée.
Fonction générique pour exécuter une commande lors d'un changement de fichier
Pour un cas plus générique, vous pouvez utiliser cette fonction :
exec-onchange()
{
local file="$1"
shift
# strip path
local filename="${file##*/}"
# strip filename
local path="${file%/*}"
if [ -z "$path" ]; then path="."; fi
# catch a custom command
local cmd="$@"
local literalFlag=""
if [ -z "$cmd" ]; then cmd="$path/$filename"; literalFlag="-Fx"; fi
exec inotifywait -q --format '%f' -e close_write,moved_to -m "$path" |
grep --line-buffered $literalFlag "$filename" |
xargs -l -i /bin/bash -c "$cmd"
}
Utilisation :
exec-onchange [file-to-watch] [command-to-execute]
Exemple d'utilisation :
exec-onchange myfile.py
Notez que l'argument est littéral, sauf si une commande personnalisée est ajoutée, auquel cas le premier argument devient une expression régulière. Bien que dans ce cas, les expressions régulières ne soient autorisées que pour la correspondance du nom de fichier, et non du chemin.
Cette fonction permet une utilisation plus complexe. Comme la compilation automatique, tout en exécutant l'exécutable compilé dès que la compilation est terminée (en utilisant un exec-onchange séparé, la compilation peut être faite tout en continuant à exécuter build/main) :
exec-onchange 'src/.*\.cpp' 'echo "{} changed"; gcc src/*.cpp -o build/main' &
exec-onchange build/main
0 votes
Possibilité de duplication de site croisé de : stackoverflow.com/questions/2972765/ ( bien qu'ici c'est le sujet =) )
0 votes
J'ai déjà référencé un duplicate cross site et il a été refusé :S ;)
4 votes
La solution de Jonathan Hartley s'appuie sur d'autres solutions proposées ici et corrige les gros problèmes des réponses les plus votées : absence de certaines modifications et inefficacité. Veuillez changer la réponse acceptée par la sienne, qui est également maintenue sur github à l'adresse suivante github.com/tartley/rerun2 (ou à une autre solution sans ces défauts)
0 votes
watch -g
se termine lorsque la sortie de la commande change, par exemple :while :; do watch -gn .1 stat -c %Z file.tex && pdflatex -interaction batchmode file.tex && pkill -HUP mupdf; done
. Où:
évalue àtrue
y-n .1
exécute la commande (stat
) toutes les 0,1 seconde.stat -c %Z
donne l'heure du dernier accès au fichier. L'inconvénient est que cela ne peut être arrêté qu'avec^Z
,kill %1
1 votes
@Zaz Au lieu de
while :; do …; done
j'utilise habituellementwhile sleep 1; do …; done
. De cette façon, je peux facilement^C
pendant lesleep
appel. De plus, il évite d'accaparer le CPU en limitant la boucle à une fréquence maximale de 1 Hz (réglable en modifiant la valeur de l'attributsleep
paramètres).