Como monitorar uma pasta e acionar uma ação da linha de comando quando um arquivo é criado ou editado?

82

Preciso configurar algum tipo de script na minha máquina Vista, para que, sempre que um arquivo seja adicionado a uma pasta específica, ele acione automaticamente um processo em segundo plano que funcione no arquivo. (O processo em segundo plano é apenas um utilitário de linha de comando que aceita o nome do arquivo como argumento, além de outras opções predefinidas.)

Eu gostaria de fazer isso usando recursos nativos do Windows, se possível, por motivos de desempenho e manutenção. Examinei o uso do Agendador de tarefas, mas depois de examinar o sistema por um tempo, não consegui entender muito bem, e nem tenho certeza se ele é capaz de fazer o que eu preciso.

Gostaria muito de receber sugestões. Obrigado!

bigmattyh
fonte
Parece que você precisa de algo como o inotify do Linux, mas para o Windows. O Jnotify pode ajudar, mas como o Java pode ser muito pesado.
Keith
11
Eu estava pensando sobre isso também ... encontrei a [página MSDN] ( msdn.microsoft.com/en-us/library/aa365261(VS.85).aspx) .
Keith
2
O link acima tem) após o aspx: msdn.microsoft.com/en-us/library/aa365261(VS.85).aspx
Dom

Respostas:

92

No trabalho, usamos o Powershell para monitorar pastas.
Pode ser usado desde o Windows Vista (.NET e PowerShell está pré-instalado) sem nenhuma ferramenta adicional.

Este script monitora uma determinada pasta e grava um arquivo de log. Você pode substituir a ação e fazer o que quiser, por exemplo, chamar uma ferramenta externa

Arquivo de log de exemplo

23/11/2014 19:22:04, criado, D: \ source \ New Text Document.txt
23/11/2014 19:22:09, Alterado, D: \ source \ New Text Document.txt
23/11/2014 19:22:09, Alterado, D: \ source \ New Text Document.txt
23/11/2014 19:22:14, Excluído, 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}

Como usar

  1. Crie um novo arquivo de texto
  2. Copie e cole o código acima
  3. Altere as seguintes configurações para suas próprias necessidades:
    • pasta para monitorar: $watcher.Path = "D:\source"
    • filtro de arquivo para incluir apenas certos tipos de arquivo: $watcher.Filter = "*.*"
    • inclua subdiretórios yes / no: $watcher.IncludeSubdirectories = $true
  4. Salve e renomeie-o para StartMonitoring.ps1
  5. Comece a monitorar clicando com o botão direito do mouse »Executar com PowerShell

Para interromper o monitoramento, basta fechar a janela do PowerShell

Leitura adicional

nixda
fonte
Funciona bem, mas qual é a função do script de parada? Eu recebo erros: "Unregister-Event: Não é possível vincular o argumento ao parâmetro 'SourceIdentifier' porque é nulo." pastebin.com/ugLB3a69
Jan Stanstrup
@ JanStanstrup Eu provavelmente confundi mais pessoas com o segundo script. Eu vou deletá-lo. Basta fechar a StartWatching.ps1janela para interromper o monitoramento. O segundo script só funciona se você incluí-lo em seu primeiro roteiro para salvar as variáveis $created, $changed, $deletedou$renamed
nixda
Obrigado pela resposta. Alguém pode sugerir se poderíamos usar o prompt do cmd, pois eu quero fazer o upload dos arquivos para o github quando alterados
m__
5

Você parece estar nas linhas corretas - você pode usar o agendador de tarefas para executar um arquivo .bat ou .cmd regularmente e esse arquivo pode começar com uma linha para verificar a existência do arquivo necessário - na verdade, eu verificaria a inexistência do arquivo; por exemplo:

@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

Você também pode modificar esse código e executá-lo em um loop com um atraso de, por exemplo, 1 minuto no loop e, em seguida, colocar uma referência ao arquivo em lotes na pasta de inicialização do 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

Existem outras maneiras de obter um atraso de acordo com a versão do Windows em execução e quais kits de recursos adicionais foram instalados, mas o comando PING praticamente funciona em todas as circunstâncias. No comando PING acima, 10 PINGS fantasmas são executados com um atraso de 6000ms (ou seja: 6 segundos) entre eles. Você pode jogar com esses valores para obter o atraso necessário entre os loops de arquivos em lote.

Linker3000
fonte
boa idéia .. btw, C: \> ping 1.1.1.1 -n 10 -w 6000 por algum motivo levou 1min 10 segundos no meu computador. mas -n 1 -w 60000 levou 1min exatamente.
barlop
@barlop - a segunda discrepância dez é devido ao -n 10vs -n 1.
@ Randolph Potter Não são 10 lotes de 6 segundos, 60 segundos? e -n 10 que você usa, deve significar 10 vezes.
barlop
Você provavelmente está certo. Eu retiro e culpo meu cabelo loiro.
Acabei usando esse loop para um lote de monitoramento IF NOT EXIST C:\NO_SUCH_FILE_EVER.foo. Hackish, mas funciona. Obrigado pela ideia.
Snekse
3

Obrigado a todos pelas sugestões.

Acabei escrevendo um VBScript que era basicamente baseado na idéia do Linker3000 de pesquisar a pasta e usar o Agendador de Tarefas para executá-lo na inicialização. Acabei obtendo a sintaxe básica desse recurso e fiz os ajustes necessários.

Eu ainda gostaria de otimizá-lo em algum momento, tendo a coragem do script em execução em um sistema orientado a eventos, mas fiquei sem tempo para trabalhar nele e, bem, isso é bom o suficiente.

Aqui está o script, caso alguém esteja interessado (com o segmento de conversão irrelevante redigido para maior clareza):

' 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

(Além disso, não quero deixar esta pergunta oficialmente sem resposta - e odeio aceitar minha própria resposta à pergunta - mas fiz um voto positivo à resposta do Linker3000 como agradecimento!)

bigmattyh
fonte
2

Você pode olhar para o DropIt (gratuito). O programa é apropriado para processar arquivos recebidos de algumas maneiras automatizadas. Você pode mover, copiar, excluir e passar parâmetros para outros programas de linha de comando para converter imagens, dividir PDFs etc.

Dom
fonte
2

Se a ação for apenas copiar arquivos alterados, você poderá usar robocopy / MON

Não sei se a robocópia usa o FileSystemWatcher ou funciona pesquisando alterações

weberjn
fonte
1

Ou você pode usar o Watch 4 Folder . Aparentemente, é Freeware, portátil e compatível com o Windows 7. Eu não tentei, mas o encontrei através de uma pesquisa na web e pensei em transmiti-lo.

Também gosto do script VBS, também apresentado no site.

Chris
fonte
Infelizmente, apenas a versão paga é portátil
nixda
Estava pensando em usar este software. Você confiaria em monitorar um compartilhamento de rede com arquivos importantes de muitos usuários?
Paul Matthews
A versão gratuita do Watch4Folder possui apenas uma entrada de "amostra" que pode ser configurada.
PeterCo 4/07
1

Também encontrei um vigia que parece bem grande, e um watchexec menor que eu não tentei.

Pysis
fonte
0

Usamos a ferramenta comercial (ou seja, não é gratuita) Folder Poll em http://www.myassays.com/folder-poll para fazer exatamente isso. É um aplicativo do Windows que inclui um aplicativo de gerenciamento amigável para permitir uma configuração fácil. Além disso, há uma opção de configuração XML. A pesquisa de pasta real é executada como um serviço do Windows (é iniciada automaticamente em cada reinicialização). Quando um novo arquivo é detectado em uma pasta pesquisada, um aplicativo pode ser iniciado automaticamente (você pode especificar seus próprios argumentos de linha de comando personalizados). Também pode fazer outras coisas, como copiar / mover arquivos. Além disso, a atividade pode ser registrada em um arquivo de log e há outras operações avançadas.

Senhor Cook
fonte