Comment surveiller un dossier et déclencher une action de ligne de commande lorsqu'un fichier est créé ou modifié?

82

Je dois configurer une sorte de script sur ma machine Vista afin que, chaque fois qu'un fichier est ajouté à un dossier particulier, il déclenche automatiquement un processus d'arrière-plan qui fonctionne sur le fichier. (Le processus d'arrière-plan est simplement un utilitaire de ligne de commande qui prend le nom du fichier en tant qu'argument, ainsi que d'autres options prédéfinies.)

Pour ce faire, j'aimerais utiliser des fonctionnalités Windows natives, si possible, pour des raisons de performances et de maintenance. J'ai envisagé d'utiliser le Planificateur de tâches, mais après avoir parcouru le système de déclenchement pendant un moment, je n'ai pas été en mesure de le comprendre, et je ne suis même pas sûr qu'il soit capable de faire ce dont j'ai besoin.

J'apprécierais toutes les suggestions. Merci!

bigmattyh
la source
On dirait que vous avez besoin de quelque chose comme l'inotify de Linux, mais pour Windows. Jnotify pourrait aider, mais comme c'est Java, il pourrait être trop lourd.
Keith
1
Je m'interrogeais aussi à ce sujet ... a trouvé la [page MSDN] ( msdn.microsoft.com/en-us/library/aa365261(VS.85).aspx) .
Keith
2
Le lien ci-dessus a) après aspx: msdn.microsoft.com/en-us/library/aa365261(VS.85).aspx
dim.

Réponses:

92

Au travail, nous utilisons Powershell pour surveiller les dossiers.
Il peut être utilisé depuis Windows Vista (les logiciels .NET et PowerShell sont préinstallés) sans aucun outil supplémentaire.

Ce script surveille un certain dossier et écrit un fichier journal. Vous pouvez remplacer l'action et faire ce que vous voulez, par exemple appeler un outil externe

Exemple de fichier journal

23/11/2014 19:22:04, Créé, D: \ source \ Nouveau document texte.txt
23/11/2014 19:22:09, Modifié, D: \ source \ Nouveau document texte.txt
23/11/2014 19:22:09, Modifié, D: \ source \ Nouveau document texte.txt
23/11/2014 19:22:14, Supprimé, D: \ source \ New Text Document.txt

StartMonitoring.ps1

### SET FOLDER TO WATCH + FILES TO WATCH + SUBFOLDERS YES/NO
    $watcher = New-Object System.IO.FileSystemWatcher
    $watcher.Path = "D:\source"
    $watcher.Filter = "*.*"
    $watcher.IncludeSubdirectories = $true
    $watcher.EnableRaisingEvents = $true  

### DEFINE ACTIONS AFTER AN EVENT IS DETECTED
    $action = { $path = $Event.SourceEventArgs.FullPath
                $changeType = $Event.SourceEventArgs.ChangeType
                $logline = "$(Get-Date), $changeType, $path"
                Add-content "D:\log.txt" -value $logline
              }    
### DECIDE WHICH EVENTS SHOULD BE WATCHED 
    Register-ObjectEvent $watcher "Created" -Action $action
    Register-ObjectEvent $watcher "Changed" -Action $action
    Register-ObjectEvent $watcher "Deleted" -Action $action
    Register-ObjectEvent $watcher "Renamed" -Action $action
    while ($true) {sleep 5}

Comment utiliser

  1. Créer un nouveau fichier texte
  2. Copier et coller le code ci-dessus
  3. Modifiez les paramètres suivants selon vos propres besoins:
    • dossier à surveiller: $watcher.Path = "D:\source"
    • filtre de fichier pour inclure uniquement certains types de fichiers: $watcher.Filter = "*.*"
    • inclure les sous-répertoires oui / non: $watcher.IncludeSubdirectories = $true
  4. Sauvegarder et renommer en StartMonitoring.ps1
  5. Démarrer la surveillance par clic droit »Exécuter avec PowerShell

Pour arrêter la surveillance, il suffit de fermer la fenêtre de PowerShell.

Lectures complémentaires

Nixda
la source
Fonctionne bien mais quelle est la fonction du script stop? J'obtiens des erreurs: "Unregister-Event: impossible de lier l'argument au paramètre 'SourceIdentifier' car il est null." pastebin.com/ugLB3a69
Jan Stanstrup
@JanStanstrup J'ai probablement confondu plus de gens avec le second script. Je vais le supprimer. Il suffit simplement de fermer la StartWatching.ps1fenêtre pour arrêter la surveillance. Le second script ne fonctionne que si vous incluez dans votre premier script pour enregistrer les variables $created, $changed, $deletedou$renamed
nixda
Merci d'avoir répondu. Quelqu'un peut-il suggérer si nous pouvions utiliser l'invite de commande parce que je veux télécharger les fichiers sur github lors de la modification
m__
5

Vous semblez être sur les bonnes lignes - vous pouvez utiliser le planificateur de tâches pour exécuter régulièrement un fichier .bat ou .cmd. Ce fichier peut commencer par une ligne pour vérifier l'existence du fichier requis - en fait, je 'vérifierais la non-existence du fichier; par exemple:

@ECHO OFF
REM Example file
IF NOT EXIST C:\SOMEWHERE\SUBFOLDER\THISFILE.THS EXIT 1
REM All this gets done if the file exists...
:
:
EXIT 0

Vous pouvez également modifier ce code et le faire exécuter en boucle avec un délai d'une minute, par exemple, puis mettre une référence au fichier de commandes dans le dossier de démarrage de Windows:

@ECHO OFF
REM Example file
:LOOP    
IF NOT EXIST C:\SOMEWHERE\SUBFOLDER\THISFILE.THS GOTO SKIP01
REM All this gets done if the file exists...
:
:
:SKIP01
REM Crafty 1 minute delay...
PING 1.1.1.1 -n 10 -w 6000 >NUL
GOTO LOOP

Il existe d'autres moyens d'obtenir un délai en fonction de la version de Windows utilisée et des kits de ressources supplémentaires installés, mais la commande PING fonctionne quasiment dans toutes les circonstances. Dans la commande PING ci-dessus, 10 PINGGES fantômes sont exécutés avec un délai de 6 000 ms (soit 6 secondes). Vous pouvez utiliser ces valeurs pour obtenir le délai nécessaire entre les boucles de fichiers batch.

Linker3000
la source
bonne idée .. d'ailleurs, C: \> ping 1.1.1.1 -n 10 -w 6000 pour une raison quelconque a pris 1min 10 secondes sur mon ordinateur. mais -n 1 -w 60000 a pris 1 minute exactement.
Barlop
@barlop - la différence est dix secondes en raison du -n 10contre -n 1.
@Randolph Potter N'est-ce pas 10 lots de 6 secondes, 60 secondes? et -n 10 que vous utilisez, devrait signifier 10 fois.
Barlop
Tu as probablement raison. Je le reprends et blâme mes cheveux blonds.
J'ai fini par utiliser cette boucle pour un lot de surveillance IF NOT EXIST C:\NO_SUCH_FILE_EVER.foo. Hackish, mais ça marche. Merci pour l'idée.
Snekse
3

Merci à tous pour les suggestions.

J'ai fini par écrire un script VBScript basé sur l'idée de Linker3000 consistant à interroger le dossier et à utiliser le Planificateur de tâches pour l'exécuter au démarrage. J'ai fini par obtenir la syntaxe de base de cette ressource et faire les ajustements nécessaires.

J'aimerais quand même l'optimiser à un moment donné, en laissant le courage du script s'exécuter sur un système piloté par les événements, mais je n'ai plus beaucoup de temps pour travailler dessus, et bien, c'est assez bon.

Voici le script, au cas où quiconque serait intéressé (avec le segment de conversion non pertinent rédigé pour des raisons de clarté):

' FOLDER TO MONITOR
strFolder = "J:\monitored-folder"

' FREQUENCY TO CHECK IT, IN SECONDS
nFrequency = 10

strComputer = "."
strQueryFolder = Replace(strFolder, "\", "\\\\")
Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" &     strComputer & "\root\cimv2") 
Set colMonitoredEvents = objWMIService.ExecNotificationQuery ("SELECT * FROM __InstanceCreationEvent WITHIN " & nFrequency & " WHERE Targetinstance ISA 'CIM_DirectoryContainsFile' and TargetInstance.GroupComponent='Win32_Directory.Name=""" & strQueryFolder & """'") 

Do 
    Set objLatestEvent = colMonitoredEvents.NextEvent
    strNewFile = objLatestEvent.TargetInstance.PartComponent
    arrNewFile = Split(strNewFile, "=")
    strFilePath = arrNewFile(1)
    strFilePath = Replace(strFilePath, "\\", "\")
    strFilePath = Replace(strFilePath, Chr(34), "")
    strFileName = Replace(strFilePath, strFolder, "")
    strTempFilePath = WScript.CreateObject("Scripting.FileSystemObject").GetSpecialFolder(2) & "\TEMP.M4A"

    ' DO THE OPERATION STUFF
    ' ...
Loop

(En outre, je ne veux pas laisser cette question officiellement sans réponse - et je déteste accepter ma propre réponse à la question - mais j'ai voté en faveur de la réponse de Linker3000 en guise de remerciement!)

bigmattyh
la source
2

Vous pouvez regarder DropIt (gratuit). Le programme convient au traitement des fichiers entrants de manière automatisée. Vous pouvez déplacer, copier, supprimer et transmettre des paramètres à d'autres programmes en ligne de commande pour convertir des images, des PDF divisés, etc.

Soleil
la source
2

Si l’action consiste uniquement à copier les fichiers modifiés, vous pouvez utiliser robocopy / MON.

Je ne sais pas si robocopy utilise FileSystemWatcher ou fonctionne en interrogeant les modifications

Weberjn
la source
1

Ou vous pouvez utiliser Watch 4 Folder . Apparemment, c'est Freeware, portable et compatible avec Windows 7. Je ne l'ai pas essayé, mais je l'ai trouvé grâce à une recherche sur le Web et j'ai pensé le transmettre.

J'aime aussi le script VBS, également présenté sur le site.

Chris
la source
Malheureusement, seule la version payante est portable
nixda
Je pensais à utiliser ce logiciel. Auriez-vous confiance qu'il surveille un partage réseau avec des fichiers importants de nombreux utilisateurs?
Paul Matthews
La version gratuite de Watch4Folder ne contient qu'un seul "exemple" d'entrée pouvant être configuré.
PeterCo
0

Nous utilisons l'outil commercial (c'est-à-dire, pas gratuit) Sondage Sondage de http://www.myassays.com/folder-poll pour le faire. C'est une application Windows qui inclut une application de gestion conviviale pour permettre une configuration facile. Il existe également une option de configuration XML. La scrutation des dossiers s’effectue en tant que service Windows (elle démarre donc à chaque redémarrage). Lorsqu'un nouveau fichier est détecté dans un dossier interrogé, une application peut être lancée automatiquement (vous pouvez spécifier vos propres arguments de ligne de commande personnalisés). Il peut aussi faire d’autres choses comme copier / déplacer des fichiers. En outre, l'activité peut être consignée dans un fichier journal et il existe d'autres opérations avancées.

Monsieur Cook
la source