J'essaie de créer un script bash qui prend 2 paramètres: un répertoire et une commande. J'ai besoin de regarder ce répertoire pour les changements et quand quelque chose a été changé, j'ai besoin d'exécuter la commande. Je suis vraiment nouveau dans le domaine des scripts et je ne suis pas vraiment sûr de ce que je fais, alors allez-y doucement. Je suis aussi sur un mac, pas linux. Tous les pointeurs ou ressources externes seraient d'une grande aide. Je sais que beaucoup de gens essaient cela sur Internet et que personne ne semble réussir à le faire. J'essaie vraiment d'imiter la fonctionnalité de la montre SASS.
#!/bin/bash
#./watch.sh $PATH $COMMAND
DIR=$1
ls -l $DIR > $DIR/.begin
#this does not work
DIFFERENCE=$(diff .begin .end)
if [ $DIFFERENCE = '\n']; then
#files are same
else
$2
fi
ls -l $DIR > $DIR/.end
Voici un exemple de surveillance des modifications dans un dossier et d’exécution du compilateur less lorsqu’il est mis à jour. Pour cela, vous avez besoin de npm
et le module onchange . La communauté de nœuds a toute une série de commandes de surveillance différentes (comme onchange). À ma connaissance, aucune d'entre elles ne contient de binaires compilés.
npm install less onchange -g
Ensuite, vous pouvez utiliser quelque chose comme:
onchange "./stylesheets/*.less" -- lessc main.less > main.css
Je préfère une commande BASH à la réponse Grunt J'ai donné quelques instants en arrière.
Pour surveiller continuellement de manière récursive le dossier (md5) et exécuter une commande lors d’une modification:
daemon() {
chsum1=""
while [[ true ]]
do
chsum2=`find src/ -type f -exec md5 {} \;`
if [[ $chsum1 != $chsum2 ]] ; then
compile
chsum1=$chsum2
fi
sleep 2
done
}
Fonctionne sur mon OS X car je n’ai pas digest
.
Sous Linux, vous pouvez utiliser md5sum
pour remplacer la commande md5
.
METHODE 1:
#!/bin/sh
check() {
dir="$1"
chsum1=`digest -a md5 $dir | awk '{print $1}'`
chsum2=$chsum1
while [ $chsum1 -eq $chsum2 ]
do
sleep 10
chsum2=`digest -a md5 $dir | awk '{print $1}'`
done
eval $2
}
check $*
Ce script prend deux paramètres [répertoire, commande]. Toutes les 10 secondes, le script exécute check()
pour voir si le dossier a été modifié. Sinon, il dort et le cycle se répète.
Dans le cas où le dossier a été modifié, votre commande est eval
s.
METHODE 2:
Utilisez un cron pour surveiller le dossier.
Vous devrez installer incron:
Sudo apt-get install incron
Et puis votre script ressemblera à quelque chose comme ça:
#!/bin/bash
eval $1
(Vous n'aurez pas besoin de spécifier le dossier car ce sera le travail du cron de surveiller le répertoire spécifié)
Vous trouverez un exemple complet ici:
Je ne peux pas croire que personne n’a encore posté ceci.
Tout d’abord, assurez-vous queinotify-tools
sont installés.
Ensuite, utilisez-les comme ceci:
logOfChanges="/tmp/changes.log.csv" # Set your file name here.
# Lock and load
inotifywait -mrcq $DIR > "$logOfChanges" &
IN_PID=$$
# Do your stuff here
...
# Kill and analyze
kill $IN_PID
cat "$logOfChanges" | while read entry; do
# Split your CSV, but beware that file names may contain spaces too.
# Just look up how to parse CSV with bash. :)
path=...
event=...
... # Other stuff like time stamps?
# Depending on the event…
case "$event" in
SOME_EVENT) myHandlingCode path ;;
...
*) myDefaultHandlingCode path ;;
done
Alternativement, utiliser --format
au lieu de -c
sur inotifywait
serait une idée.
Juste man inotifywait
et man inotifywatch
pour plus d'infos.
probablement le moyen le plus rapide de le faire .. (sur repo 1G git, retour sous 1sec.)
#!/bin/bash
watch() {
echo watching folder $1/ every $2 secs.
while [[ true ]]
do
files=`find $1 -type f -mtime -$2s`
if [[ $files == "" ]] ; then
echo "nothing changed"
else
echo changed, $files
fi
sleep $2
done
}
watch folder 3
Sous Mac OS X, vous pouvez simplement cliquer avec le bouton droit de la souris sur un dossier, puis cliquer sur "Configuration des actions sur les dossiers". Cela vous permettra d'attacher des actions à un dossier, c'est-à-dire des scripts à exécuter.
OS X est livré avec un certain nombre de scripts prédéfinis, ou vous pouvez créer les vôtres.
Presque 3 ans plus tard, je recommanderais cette solution basée sur le grognement.
J'ai créé un exemple de travail ici https://github.com/reggi/watch-execute .
Voici le Gruntfile.js
:
module.exports = function (grunt) {
grunt.initConfig({
Shell: {
run_file:{
command: 'sh ./bash.sh',
options: {
stdout: true
}
}
},
watch: {
run_file: {
files: ["./watchme/*"],
tasks: ["Shell:run_file"]
}
}
});
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-Shell');
};
J'ai écrit un utilitaire général appelé watchfile
pour simplifier ces types d'opérations.
Il est moins puissant que inotifywatch
, mais je préfère un utilitaire plus simple et moins détaillé.
Pour la tâche souhaitée, vous souhaitez contrôler si des fichiers du répertoire en cours ont été modifiés. Pour lister tous les fichiers de manière récursive dans le répertoire actuel:
find . -type f
Pour sortir les informations d'horodatage de chacun de ces fichiers:
find . -type f -print0 | xargs -0 stat
Maintenant, vous pouvez surveiller cette sortie avec l'utilitaire watchfile
et exécuter une commande CMD
lorsque ces informations changent:
watchfile -s "find . -type f -print0 | xargs -0 stat" -e CMD
#!/bin/bash
# Author: Devonte
# NGINX WATCH DAEMON
# Place file in root of nginx folder /etc/nginx
# This will test your nginx config on any change and
# if there are no problems it will reload your configuration
# USAGE: sh nginx-watch.sh
dir=`dirname $0`
checksum_initial=`tar -cf - $dir | md5sum | awk '{print $1}'`
checksum_now=$checksum_initial
# Start nginx
nginx
while true
do
sleep 3
checksum_now=`tar -cf - $dir | md5sum | awk '{print $1}'`
if [ $checksum_initial != $checksum_now ]; then
echo "[ NGINX ] A configuration file changed. Reloading..."
nginx -t && nginx -s reload;
fi
checksum_initial=$checksum_now
done
Pourquoi ne pas utiliser AppleScript
http://www.tuaw.com/2009/03/26/applescript-exploring-the-power-of-folder-actions-part-iii/
on adding folder items to this_folder after receiving added_items
tell application "Finder"
...
Voici un modèle à utiliser, il vérifie toutes les 120 secondes les modifications apportées au répertoire passé et indique la création de répertoires, de fichiers ou de canaux de noms. Si vous souhaitez également exécuter des commandes lorsque quelque chose est supprimé, vérifiez mon autre réponse sur stackoverflow pour des exemples supplémentaires de bouclage.
#!/usr/bin/env bash
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
}
Si vous remplacez les lignes echo
ci-dessus par eval <some command>
pour chaque type d'action surveillée, vous serez plus près de l'automatisation des actions. Et si vous souhaitez voir à quoi ressemble le texte ci-dessus lorsqu’il est utilisé dans un script, consultez la dernière version de script pour le projet sur lequel j’ai travaillé pour l’automatisation du cryptage et du décryptage via gpg et tar.
Si vous devez uniquement rechercher les fichiers en cours de création/suppression au premier niveau (sans vérifier les sous-dossiers), vous pouvez utiliser les éléments suivants.
Il utilise peu de ressources et peut donc réagir rapidement. Je l'utilise pour vérifier si un fichier a été modifié.
#!/bin/bash
file="$1"
shift
tmp=$(mktemp)
trap 'rm "$tmp"' EXIT
while true; do
while [ ! "$tmp" -ot "$file" ]; do
sleep 0.5
done
eval "$@ &"
echo $! > "$tmp"
wait
done