Jak monitorować folder i wyzwalać akcję z wiersza poleceń, gdy plik jest tworzony lub edytowany?

82

Muszę skonfigurować jakiś skrypt na moim komputerze z systemem Vista, aby za każdym razem, gdy plik został dodany do określonego folderu, automatycznie uruchamiał proces działający w tle na pliku. (Proces w tle to po prostu narzędzie wiersza polecenia, które przyjmuje nazwę pliku jako argument, wraz z kilkoma innymi predefiniowanymi opcjami).

Chciałbym to zrobić przy użyciu natywnych funkcji systemu Windows, jeśli to możliwe, ze względu na wydajność i konserwację. Zastanawiałem się nad użyciem Harmonogramu zadań, ale po pewnym czasie przestudiowania systemu wyzwalania nie byłem w stanie zrozumieć go zbyt dobrze i nawet nie jestem pewien, czy jest on w stanie zrobić to, czego potrzebuję.

Byłbym wdzięczny za wszelkie sugestie. Dzięki!

bigmattyh
źródło
Wygląda na to, że potrzebujesz czegoś takiego jak Linux inotify, ale dla Windows. Jnotify może pomóc, ale ponieważ jest to Java może być zbyt ciężka.
Keith,
1
Też się nad tym zastanawiałem ... znalazłem [stronę MSDN] ( msdn.microsoft.com/en-us/library/aa365261(VS.85).aspx) .
Keith
2
Link powyżej ma) po aspx: msdn.microsoft.com/en-us/library/aa365261(VS.85).aspx
niedz

Odpowiedzi:

92

W pracy używamy Powershell do monitorowania folderów.
Można go używać od czasu zainstalowania systemu Windows Vista (.NET i PowerShell) bez żadnych dodatkowych narzędzi.

Ten skrypt monitoruje określony folder i zapisuje plik dziennika. Możesz zastąpić akcję i zrobić, co chcesz, np. Wezwać narzędzie zewnętrzne

Przykładowy plik dziennika

23.11.2014, 19:22:04, Utworzono, D: \ source \ New Text Document.txt
23.11.2014, 19:22:09, Zmieniono, D: \ source \ New Text Document.txt
23.11.2014, 19:22:09, Zmieniono, D: \ source \ New Text Document.txt
23.11.2014, 19:22:14, Usunięte, 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}

Jak używać

  1. Utwórz nowy plik tekstowy
  2. Skopiuj i wklej powyższy kod
  3. Zmień następujące ustawienia według własnych potrzeb:
    • folder do monitorowania: $watcher.Path = "D:\source"
    • filtr plików, aby uwzględnić tylko niektóre typy plików: $watcher.Filter = "*.*"
    • obejmują podkatalogi tak / nie: $watcher.IncludeSubdirectories = $true
  4. Zapisz i zmień nazwę na StartMonitoring.ps1
  5. Rozpocznij monitorowanie klikając prawym przyciskiem myszy »Uruchom za pomocą PowerShell

Aby zatrzymać monitorowanie, wystarczy zamknąć okno PowerShell

Dalsza lektura

nixda
źródło
Działa ładnie, ale jaka jest funkcja skryptu stop? Występują błędy: „Wyrejestruj zdarzenie: Nie można powiązać argumentu z parametrem„ SourceIdentifier ”, ponieważ jest on pusty.” pastebin.com/ugLB3a69
Jan Stanstrup
@JanStanstrup Prawdopodobnie pomyliłem więcej osób z drugim skryptem. Usunę to. Wystarczy po prostu zamknąć StartWatching.ps1okno, aby zatrzymać monitorowanie. Drugi skrypt działa tylko jeśli zawierają go w swoim pierwszym scenariuszem, aby zapisać zmienne $created, $changed, $deletedlub$renamed
nixda
Dziękuję za odpowiedź. Czy ktoś może zasugerować, czy moglibyśmy użyć polecenia cmd, ponieważ chcę przesłać pliki do github po zmianie
m__
5

Wygląda na to, że masz właściwe linie - możesz użyć harmonogramu zadań do regularnego uruchamiania pliku .bat lub .cmd, a plik ten może zaczynać się od linii sprawdzającej istnienie wymaganego pliku - w rzeczywistości ja sprawdził, czy plik nie istnieje; na przykład:

@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

Możesz również zmodyfikować ten kod i uruchomić go w pętli z, powiedzmy, 1-minutowym opóźnieniem w pętli, a następnie umieścić odniesienie do pliku wsadowego w folderze startowym systemu 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

Istnieją inne sposoby osiągnięcia opóźnienia w zależności od wersji systemu Windows i zainstalowanych dodatkowych zestawów zasobów, ale polecenie PING działa właściwie we wszystkich okolicznościach. W powyższym poleceniu PING 10 fantomowych PINGÓW jest wykonywanych z opóźnieniem 6000ms (tj. 6 sekund) między nimi, możesz grać tymi wartościami, aby osiągnąć potrzebne opóźnienie między pętlami plików wsadowych.

Linker3000
źródło
fajny pomysł .. btw, C: \> ping 1.1.1.1 -n 10 -w 6000 z jakiegoś powodu zajęło 1 min 10 sekund na moim komputerze. ale -n 1 -w 60000 zajęło dokładnie 1 minutę.
barlop
@barlop - drugi dziesięć rozbieżność jest spowodowana -n 10VS -n 1.
@Randolph Potter Czy nie 10 partii 6 sekund, 60 sekund? i -n 10, którego używasz, powinno oznaczać 10 razy.
barlop
Pewnie masz rację. Cofam je i obwiniam blond włosy.
Skończyło się na użyciu tej pętli do monitorowania partii IF NOT EXIST C:\NO_SUCH_FILE_EVER.foo. Hackish, ale działa. Dzięki za pomysł.
Snekse
3

Dzięki wszystkim za sugestie.

Skończyło się na tym, że napisałem VBScript, który w przybliżeniu opierał się na pomyśle Linker3000 o sondowaniu folderu i użyciu Harmonogramu zadań, aby uruchomić go podczas uruchamiania. Ostatecznie otrzymałem podstawową składnię z tego zasobu i wprowadziłem wymagane poprawki.

Nadal chciałbym go zoptymalizować w pewnym momencie, mając wnętrzności skryptu w systemie sterowanym zdarzeniami, ale zabrakło mi czasu na pracę nad nim, i, cóż, to wystarczy.

Oto skrypt, na wypadek, gdyby ktoś był zainteresowany (z nieistotnym segmentem konwersji zredagowanym dla przejrzystości):

' 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

(Nie chcę też pozostawiać tego pytania oficjalnie bez odpowiedzi - i nienawidzę przyjmować własnej odpowiedzi na to pytanie - ale podziękowałem za odpowiedź Linker3000!)

bigmattyh
źródło
2

Możesz spojrzeć na DropIt (bezpłatny). Program nadaje się do przetwarzania plików przychodzących na kilka zautomatyzowanych sposobów. Możesz przenosić, kopiować, usuwać i przekazywać parametry do innych programów wiersza poleceń w celu konwersji obrazów, dzielenia plików PDF itp.

Słońce
źródło
2

Jeśli akcja polega tylko na skopiowaniu zmienionych plików, możesz użyć robocopy / MON

Nie wiem, czy robocopy korzysta z FileSystemWatcher lub działa poprzez odpytywanie o zmiany

weberjn
źródło
1

Lub możesz użyć Watch 4 Folder . Najwyraźniej jest darmowy, przenośny i kompatybilny z Windows 7. Nie wypróbowałem go, ale znalazłem go w wyszukiwarce i pomyślałem, że go przekażę.

Podoba mi się również skrypt VBS, również dostępny na stronie.

Chris
źródło
Niestety tylko wersja płatna jest przenośna
nixda
Myślałem o korzystaniu z tego oprogramowania. Czy możesz zaufać, że monitoruje udział sieciowy z ważnymi plikami wielu użytkowników?
Paul Matthews,
Darmowa wersja Watch4Folder ma tylko jeden „przykładowy” wpis, który można skonfigurować.
PeterCo
0

Używamy do tego celu komercyjnego narzędzia (tj. Nie jest to bezpłatne) Ankieta dotycząca folderu z http://www.myassays.com/folder-poll . Jest to aplikacja Windows, która zawiera przyjazną dla użytkownika aplikację menedżera, która umożliwia łatwą konfigurację. Istnieje również opcja konfiguracji XML. Rzeczywiste odpytywanie folderów działa jako usługa systemu Windows (więc uruchamia się automatycznie przy każdym ponownym uruchomieniu). Po wykryciu nowego pliku w folderze odpytywanym aplikacja może zostać uruchomiona automatycznie (możesz podać własne niestandardowe argumenty wiersza poleceń). Może także wykonywać inne czynności, takie jak kopiowanie / przenoszenie plików. Ponadto aktywność można zarejestrować w pliku dziennika i istnieją inne zaawansowane operacje.

Pan Cook
źródło