627 votes

Comment exécuter une commande à chaque fois qu'un fichier est modifié ?

Je veux un moyen simple et rapide d'exécuter une commande à chaque fois qu'un fichier est modifié. Je veux quelque chose de très simple, quelque chose que je laisserai tourner sur un terminal et que je fermerai dès que j'aurai fini de travailler sur ce fichier.

Actuellement, j'utilise ceci :

while read; do ./myfile.py ; done

Et ensuite je dois aller dans ce terminal et appuyer sur Enter chaque fois que j'enregistre ce fichier sur mon éditeur. Ce que je veux, c'est quelque chose comme ça :

while sleep_until_file_has_changed myfile.py ; do ./myfile.py ; done

Ou toute autre solution aussi simple que cela.

BTW : J'utilise Vim, et je sais que je peux ajouter une autocommande pour exécuter quelque chose sur BufWrite, mais ce n'est pas le genre de solution que je veux maintenant.

Mise à jour : Je veux quelque chose de simple, jetable si possible. De plus, je veux quelque chose qui s'exécute dans un terminal car je veux voir la sortie du programme (je veux voir les messages d'erreur).

A propos des réponses : Merci pour toutes vos réponses ! Elles sont toutes très bonnes, et chacune adopte une approche très différente des autres. Comme je ne dois en accepter qu'une seule, j'accepte celle que j'ai effectivement utilisée (elle était simple, rapide et facile à mémoriser), même si je sais qu'elle n'est pas la plus élégante.

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)

3voto

Tails Points 131

Vérifiez https://github.com/watchexec/watchexec .

watchexec est un outil simple et autonome qui surveille un chemin et exécute une commande dès qu'il détecte des modifications.

Exemple

Surveille tous les fichiers JavaScript, CSS et HTML du répertoire actuel et de tous les sous-répertoires pour détecter les changements, et lance l'exécution lorsqu'un changement est détecté :

$ watchexec --exts js,css,html make

2voto

Jonathan Hartley Points 924

J'ai écrit un programme Python pour faire exactement cela, appelé rerun .

MISE À JOUR : Cette réponse est un script Python qui sonde les changements, ce qui est utile dans certaines circonstances. Pour un script Bash sous Linux uniquement qui utilise inotify, voir mon autre réponse, recherchez 'rerun2' sur cette page.

Installer pour Python2 ou Python3 avec :

pip install --user rerun

et l'utilisation est très simple :

rerun "COMMAND"

La commande est attendue comme un seul argument, et non comme une séquence d'arguments séparés par des espaces. Par conséquent, il faut la citer comme indiqué, ce qui réduit le nombre de caractères d'échappement supplémentaires que vous auriez dû ajouter. Tapez simplement la commande comme vous l'auriez fait sur la ligne de commande, mais entre guillemets.

Par défaut, il surveille tous les fichiers dans ou sous le répertoire actuel, en ignorant des choses comme les répertoires de contrôle de source connus, .git, .svn, etc.

Les drapeaux optionnels incluent '-i NAME' qui ignore les changements dans les fichiers ou répertoires nommés. Cette option peut être donnée plusieurs fois.

Puisque c'est un script Python, il doit exécuter la commande en tant que sous-processus, et nous utilisons une nouvelle instance du script actuel de l'utilisateur pour interpréter 'COMMAND' et décider quel processus exécuter réellement. Cependant, si votre commande contient des alias script et autres définis dans .bashrc, ils ne seront pas chargés par le sous-shell. Pour résoudre ce problème, vous pouvez donner à rerun l'option '-I', pour utiliser des sous-shells interactifs (alias 'login'). Ceci est plus lent et plus sujet aux erreurs que le démarrage d'un script normal, parce qu'il doit sourcer votre .bashrc.

Je l'utilise avec Python 3, mais la dernière fois que j'ai vérifié, rerun fonctionnait toujours avec Python 2.

L'arme à double tranchant est qu'il utilise le sondage au lieu de l'inotify. Le bon côté des choses, c'est qu'elle fonctionne sur tous les systèmes d'exploitation. De plus, elle est meilleure que d'autres solutions présentées ici en ce sens qu'elle n'exécute la commande donnée qu'une seule fois pour un ensemble de modifications du système de fichiers, et non pas une fois par fichier modifié, tout en exécutant la commande une seconde fois si un fichier change à nouveau pendant l'exécution de la commande.

L'inconvénient, c'est que l'interrogation signifie qu'il y a une latence de 0,0 à 1,0 seconde, et bien sûr, c'est lent pour surveiller des répertoires extrêmement grands. Cela dit, je n'ai jamais rencontré de projet suffisamment grand pour que cela soit perceptible, tant que vous utilisez '-i' pour ignorer les éléments importants comme votre virtualenv et vos node_modules.

Hmmm. rerun m'a été indispensable pendant des années - je l'utilise essentiellement huit heures par jour pour exécuter des tests, reconstruire des fichiers de points au fur et à mesure que je les modifie, etc. Mais maintenant que j'en suis à taper ce texte ici, il est clair que je dois passer à une solution qui utilise inotify (je n'utilise plus Windows ou OSX.) et qui est écrite en Bash (donc qui fonctionne avec des alias sans aucun bidouillage supplémentaire.)

0 votes

Cette réponse n'est pas du tout aussi bonne que mon autre réponse (rerun2).

1 votes

De toutes les solutions que j'ai essayées pour Mac OS X en 2020 rerun a donné les meilleurs résultats pour l'exécution make test sur tout projet (par exemple Elixir, Python, ...) $ pip3 install rerun $ rerun --verbose --ignore=_build --ignore=deps "make test-unit"

2voto

Hefewe1zen Points 1774

Pour ceux qui utilisent OS X, vous pouvez utiliser un LaunchAgent pour surveiller les modifications d'un chemin/fichier et agir en conséquence. Pour info, LaunchControl est une bonne application pour créer/modifier/supprimer facilement des démons/agents.

( exemple tiré d'ici )

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC -//Apple Computer//DTD PLIST 1.0//EN
http://www.apple.com/DTDs/PropertyList-1.0.dtd>
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>test</string>
    <key>ProgramArguments</key>
    <array>
        <string>say</string>
        <string>yy</string>
    </array>
    <key>WatchPaths</key>
    <array>
        <string>~/Desktop/</string>
    </array>
</dict>
</plist>

2voto

MrCheatak Points 332

J'ai un GIST pour cela et l'utilisation est assez simple.

watchfiles <cmd> <paths...>

https://gist.github.com/thiagoh/5d8f53bfb64985b94e5bc8b3844dba55

2voto

SystematicFrank Points 141

Comme d'autres l'ont fait, j'ai également écrit un outil léger en ligne de commande pour faire cela. Il est entièrement documenté, testé et modulaire.

Watch-Do

Installation

Vous pouvez l'installer (si vous avez Python3 et pip) en utilisant :

pip3 install git+https://github.com/vimist/watch-do

Utilisation

Utilisez-le immédiatement en courant :

watch-do -w my_file -d 'echo %f changed'

Aperçu des caractéristiques

  • Supporte le globbing de fichiers (utiliser -w '*.py' o -w '**/*.py' )
  • Exécuter des commandes multiples sur un changement de fichier (il suffit de spécifier l'option -d drapeau à nouveau)
  • Maintient dynamiquement la liste des fichiers à surveiller si le globbing est utilisé ( -r pour l'activer)
  • Plusieurs façons de "surveiller" un fichier :
    • Temps de modification (par défaut)
    • Hachage de fichier
    • Il est facile de mettre en œuvre son propre système (c'est le ModificationTime watcher)
  • Conception modulaire. Si vous voulez que des commandes soient exécutées, lorsqu'un fichier est accédé, il est trivial d'écrire votre propre watcher (mécanisme qui détermine si les doers doivent être exécutés).

1 votes

Ma réponse préférée !

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X