Comment détecter de nouveaux fichiers dans un dossier avec un script bash ? Je voudrais traiter les fichiers dès qu'ils sont créés dans le dossier. Est-ce possible de le faire ou dois-je planifier un script avec cron qui vérifie les nouveaux fichiers chaque minute ou plus?
Vous devriez envisager d'utiliser inotifywait
, par exemple:
inotifywait -m /path -e create -e moved_to |
while read dir action file; do
echo "The file '$file' appeared in directory '$dir' via '$action'"
# do something with the file
done
Dans Ubuntu inotifywait
est fourni par le inotify-tools
paquet. À partir de la version 3.13 (actuelle dans Ubuntu 12.04) inotifywait
inclura le nom de fichier sans l'option -f. Les anciennes versions peuvent devoir être contraintes. Il est important de noter que le -e
l'option pour inotifywait
est la meilleure façon de filtrer les événements. De plus, votre commande read
peut affecter la sortie positionnelle à plusieurs variables que vous pouvez choisir d'utiliser ou d'ignorer. Il n'est pas nécessaire d'utiliser grep/sed/awk pour prétraiter la sortie.
Je viens de préparer cela, et je ne vois pas d'énormes problèmes avec cela, à part une petite chance de manquer des fichiers entre les vérifications.
while true
do
touch ./lastwatch
sleep 10
find /YOUR/WATCH/PATH -cnewer ./lastwatch -exec SOMECOMMAND {} \;
done
Si le traitement de vos fichiers ne prend pas trop de temps, vous ne devriez manquer aucun nouveau fichier. Vous pouvez également décrire les activités ... Ce n'est pas à l'épreuve des balles, mais cela sert à certaines fins sans outils externes comme inotify.
Je préfère incron
, car c'est plus facile à gérer. Il s'agit essentiellement d'un service qui exploite inotify
et vous pouvez configurer des configurations pour prendre des mesures en fonction des opérations de modification de fichier.
Ex:
<directory> <file change mask> <command or action> options
/var/www/html IN_CREATE /root/scripts/backup.sh
Vous pouvez voir un exemple complet ici: http://www.cyberciti.biz/faq/linux-inotify-examples-to-replicate-directories/
Vous pouvez utiliser watch
dans votre script
watch -n 0.1 ls <your_folder>
Surveille votre dossier et vous répertorie tout ce qu'il contient toutes les 0,1 secondes
Inconvénient
N'est pas en temps réel, donc si un fichier a été créé et supprimé en moins de 0,1 seconde, cela ne fonctionnerait pas, watch
ne prend en charge qu'un minimum de 0,1 seconde.
Je suppose que le dossier cible (je l'appellerai isempty
juste pour plus de commodité) est vide et vous attendez qu'un ou plusieurs fichiers y soient déposés.
Vous pouvez utiliser la commande suivante:
ls -1A isempty | wc -l
juste pour vérifier si le dossier est toujours vide, en fait il retournera un 0 s'il n'y a pas de nouveau fichier (d'où le dossier isempty
est toujours vide) ou, d'autre part, il retournera une valeur supérieure de 0 (en fait le nombre de fichiers actuellement dans le dossier).
Cela dit, un test idiot si/alors peut faire le reste du travail:
if [ $(ls -1A isempty | wc -l) -gt 0 ] ; then do_something ; fi
Bien sûr, la fonction do_something
Devra manipuler le (s) fichier (s) dans le dossier isempty
puis le (les) supprimer du dossier lui-même après le traitement.
L'ajout d'une ligne comme celle-ci dans votre crontab exécutera la vérification une fois par minute et déclenchera l'action do_something
Si le dossier n'est pas vide bien sûr:
* * * * * if [ $(ls -1A isempty | wc -l) -gt 0 ] ; then do_something ; fi
entr
Utiliser entr
est la nouvelle façon de le faire (c'est multi-plateforme). Remarque entr
n'utilise pas l'interrogation, ce qui lui donne un énorme avantage sur de nombreuses alternatives.
Utilise
kqueue(2)
ouinotify(7)
pour éviter l'interrogation.entr
a été écrit pour rendre la rétroaction rapide et les tests automatisés naturels et complètement ordinaires.
Sur BSD, il utilise pledge(2)
Vous pouvez l'installer avec
apt-get install entr
dnf install entr
brew install entr
Vous pouvez suivre un répertoire pour de nouveaux ajouts en utilisant
while $(true); do
# echo ./my_watch_dir | entr -dnr echo "Running trigger..."
echo ./my_watch_dir | entr -dnr ##MY COMMAND##
done;
Explication des options (à partir des documents),
-d
Suivez les répertoires des fichiers normaux fournis en entrée et quittez si un nouveau fichier est ajouté. Cette option permet également de spécifier explicitement les répertoires. Les fichiers dont le nom commence par "." Sont ignorés.-n
Exécuter en mode non interactif. Dans ce mode, entr n'essaie pas de lire le TTY ni de modifier ses propriétés.-r
Recharger un processus enfant persistant. Comme pour le mode de fonctionnement standard, un utilitaire qui se termine n'est pas exécuté de nouveau tant qu'un événement de système de fichiers ou de clavier n'est pas traité.SIGTERM
est utilisé pour terminer l'utilitaire avant son redémarrage. Un groupe de processus est créé pour empêcher les scripts Shell de masquer les signaux.entr
attend la fermeture de l'utilitaire pour s'assurer que les ressources telles que les sockets ont été fermées. Le contrôle du TTY n'est pas transféré au processus enfant.
Si vous voulez détecter de nouveaux fichiers, puis traitez-les et à la fin supprimez les fichiers en cours, vous pouvez utiliser systemd.path . Cette méthode repose sur inotify. Il y a une option DirectoryNotEmpty, donc systemd peut exécuter votre script toujours quand il détecte des fichiers dans le répertoire. Vous devez vous rappeler que cela ne fonctionnera que si vous pouvez supprimer les fichiers traités et que le script laisse le répertoire vide.
Préparez d'abord le fichier mymonitor.service
[Unit]
Description=Start the script
[Service]
Type=oneshot
ExecStart=/path/to/your/script
allez ensuite dans mymonitor.path pour définir le chemin
[Unit]
Description= Triggers the service
[Path]
DirectoryNotEmpty=/path/to/monitor
[Install]
WantedBy=multi-user.target
Si le nom du fichier .path est le même que le nom du service, il n'est pas nécessaire de spécifier le nom du service dans le fichier .path.
Il se base sur Surveillance de l'accès aux fichiers pour les nuls
Bash ne peut pas faire cela facilement. Vous devez essentiellement obtenir une liste de tous les fichiers du dossier et obtenir périodiquement une nouvelle liste et les comparer pour voir ce qui a changé.
Ce que vous recherchez s'appelle inotify. Son intégré dans le noyau Linux et vous pouvez essentiellement rester là en attendant que quelque chose se produise, à quel point inotify revient et dit `` Hé, il y a un nouveau fichier appelé foobar ''
Pour accomplir ce que vous voulez, vous devez passer à quelque chose comme Perl et utiliser Linux :: Inotify2 (python supporte probablement aussi inotify, mais je suis une personne Perl).
Cela fonctionne sous cygwin et Linux. Certaines des solutions précédentes qui écrivent un fichier provoquent le thrash du disque. Cette scipt n'a pas ce problème:
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
Ci-dessous se trouve une version abrégée de l'exemple sur stackoverflow que j'ai testé et incorporé dans l'un de mes projets qui nécessite la surveillance de répertoires spécifiques.
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
}
Voici un lien vers un script qui utilise une version modifiée de ci-dessus pour décrypter automatiquement les fichiers ou répertoires trouvés dans son point de montage sshfs; le projet susmentionné.