Come monitorare una cartella e attivare un'azione della riga di comando quando un file viene creato o modificato?


82

Devo impostare una sorta di script sul mio computer Vista, in modo che ogni volta che un file viene aggiunto a una determinata cartella, si avvii automaticamente un processo in background che opera sul file. (Il processo in background è solo un'utilità della riga di comando che accetta il nome del file come argomento, insieme ad alcune altre opzioni predefinite.)

Mi piacerebbe farlo utilizzando le funzionalità native di Windows, se possibile, per motivi di prestazioni e manutenzione. Ho esaminato l'uso di Utilità di pianificazione, ma dopo aver esaminato il sistema di trigger per un po ', non sono stato in grado di dargli un senso e non sono nemmeno sicuro che sia in grado di fare ciò di cui ho bisogno.

Gradirei qualsiasi suggerimento. Grazie!


Sembra che tu abbia bisogno di qualcosa come l'inotify di Linux, ma per Windows. Jnotify potrebbe aiutare, ma dal momento che è Java potrebbe essere troppo pesante.
Keith,

1
Mi chiedevo anche questo ... ho trovato la [pagina MSDN] ( msdn.microsoft.com/en-us/library/aa365261(VS.85).aspx) .
Keith,

Risposte:


92

Al lavoro utilizziamo Powershell per monitorare le cartelle.
Può essere utilizzato da Windows Vista (.NET e PowerShell sono preinstallati) senza strumenti aggiuntivi.

Questo script controlla una determinata cartella e scrive un file di registro. È possibile sostituire l'azione e fare quello che vuoi, ad esempio chiamare uno strumento esterno

File di registro di esempio

23/11/2014 19:22:04, Creato, D: \ source \ New Text Document.txt
23/11/2014 19:22:09, Modificato, D: \ source \ New Text Document.txt
23/11/2014 19:22:09, Modificato, D: \ source \ New Text Document.txt
23/11/2014 19:22:14, Cancella, 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}

Come usare

  1. Crea un nuovo file di testo
  2. Copia e incolla il codice sopra
  3. Modificare le seguenti impostazioni in base alle proprie esigenze:
    • cartella da monitorare: $watcher.Path = "D:\source"
    • filtro file per includere solo determinati tipi di file: $watcher.Filter = "*.*"
    • include sottodirectory sì / no: $watcher.IncludeSubdirectories = $true
  4. Salvalo e rinominalo in StartMonitoring.ps1
  5. Inizia il monitoraggio con il tasto destro del mouse »Esegui con PowerShell

Per interrompere il monitoraggio, è sufficiente chiudere la finestra di PowerShell

Ulteriori letture


Funziona bene, ma qual è la funzione dello script di arresto? Ottengo errori: "Unregister-Event: impossibile associare l'argomento al parametro 'SourceIdentifier' perché è null." pastebin.com/ugLB3a69
Jan Stanstrup,

@JanStanstrup Probabilmente ho confuso più persone con il secondo script. Lo cancellerò. Basta chiudere semplicemente la StartWatching.ps1finestra per interrompere il monitoraggio. Il secondo script funziona solo se si include nel vostro primo script per salvare i variabili $created, $changed, $deletedo$renamed
nixda

Grazie per la risposta. Qualcuno può suggerire se potremmo usare il cmd prompt poiché voglio caricare i file su github quando cambiati
m__

5

Sembra che tu sia sulle linee giuste - potresti utilizzare l'utilità di pianificazione per eseguire un file .bat o .cmd su base regolare e quel file potrebbe iniziare con una riga per verificare l'esistenza del file richiesto - in effetti, I verificherebbe l'esistenza del file; per esempio:

@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

Puoi anche modificare questo codice e farlo funzionare in un ciclo con un ritardo, diciamo, 1 minuto nel ciclo e quindi inserire un riferimento al file batch nella cartella di avvio di 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

Esistono altri modi per ottenere un ritardo in base alla versione di Windows in esecuzione e quali kit di risorse aggiuntivi sono stati installati, ma il comando PING funziona praticamente in tutte le circostanze. Nel comando PING sopra, 10 Phantom PINGS vengono eseguiti con un ritardo di 6000 ms (ovvero: 6 secondi) tra loro, è possibile giocare con questi valori per ottenere il ritardo necessario tra i loop di file batch.


bella idea .. btw, C: \> ping 1.1.1.1 -n 10 -w 6000 per qualche motivo ho impiegato 1 minuto e 10 secondi sul mio computer. ma -n 1 -w 60000 impiegò esattamente 1 minuto.
barlop

@barlop - il dieci secondi discrepanza è dovuta al -n 10vs -n 1.

@Randolph Potter Non sono 10 lotti di 6 secondi, 60 secondi? e -n 10 che usi, dovrebbe significare 10 volte.
barlop il

Probabilmente hai ragione. Lo riprendo e incolpo i miei capelli biondi.

Ho finito per usare questo loop per un batch di monitoraggio IF NOT EXIST C:\NO_SUCH_FILE_EVER.foo. Hackish, ma funziona. Grazie per l'idea
Snekse,

3

Grazie a tutti per i suggerimenti.

Ho finito per scrivere un VBScript che si basava approssimativamente sull'idea di Linker3000 di eseguire il polling della cartella e di utilizzare l'Utilità di pianificazione per farlo funzionare all'avvio. Ho finito per ottenere la sintassi di base da questa risorsa e ho apportato le modifiche necessarie.

Vorrei ancora ottimizzarlo a un certo punto, facendo funzionare l'intestino dello script su un sistema guidato da eventi, ma ho poco tempo per lavorarci su, e, beh, questo è abbastanza buono.

Ecco la sceneggiatura, nel caso qualcuno fosse interessato (con il segmento di conversione irrilevante redatto per chiarezza):

' 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

(Inoltre, non voglio lasciare questa domanda ufficialmente senza risposta - e odio accettare la mia risposta alla domanda - ma ho votato la risposta di Linker3000 come ringraziamento!)


2

Potresti guardare DropIt (gratuito). Il programma è appropriato per l'elaborazione dei file in arrivo in alcuni modi automatizzati. È possibile spostare, copiare, eliminare e passare parametri ad altri programmi della riga di comando per convertire immagini, dividere PDF, ecc.


2

Se l'azione è solo per copiare i file modificati, è possibile utilizzare robocopy / MON

Non so se robocopy utilizza FileSystemWatcher o funziona eseguendo il polling per le modifiche


1

Oppure potresti usare la cartella Watch 4 . Apparentemente è Freeware, portatile e compatibile con Windows 7. Non l'ho provato, ma l'ho trovato attraverso una ricerca sul web e ho pensato di passarlo.

Mi piace anche lo script VBS, presente anche sul sito.


Purtroppo solo la versione a pagamento è portatile
nixda,

Stavo pensando di utilizzare questo software. Ti fideresti di monitorare una condivisione di rete con file importanti di molti utenti?
Paul Matthews,

La versione gratuita di Watch4Folder ha solo una voce "campione" che può essere configurata.
PeterCo


0

Per fare questo, utilizziamo lo Strumento per le cartelle dello strumento commerciale (cioè non gratuito) di http://www.myassays.com/folder-poll . È un'applicazione Windows che include un'applicazione di gestione intuitiva per consentire una facile configurazione. Inoltre, esiste un'opzione di configurazione XML. Il polling effettivo delle cartelle viene eseguito come servizio Windows (quindi si avvia automaticamente ad ogni riavvio). Quando viene rilevato un nuovo file in una cartella polling, è possibile avviare automaticamente un'applicazione (è possibile specificare i propri argomenti personalizzati della riga di comando). Può fare anche altre cose come copiare / spostare file. Inoltre, l'attività può essere registrata in un file di registro e ci sono altre operazioni avanzate.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.