Monitor de carpeta Powershell/ejecución por lotes

Monitor de carpeta Powershell/ejecución por lotes

Soy nuevo en Powershell. Encontré un script que funciona con lo que necesito, más o menos.

Lo que estoy buscando es un script para monitorear una carpeta en busca de nombres/tipos de archivos específicos. Dependiendo del nombre/tipo de archivo, quiero que ejecute un determinado archivo por lotes para ejecutar un comando para una utilidad de servidor.

¿Cómo exactamente lograría esto? Encontré este script y agregué un elemento de invocación para iniciar un archivo bat cuando un archivo como PDF llega a la carpeta. Sin embargo, necesito filtrarlo y hacer que inicie un archivo bat diferente según el nombre del archivo. Lo que tengo actualmente, invocará el archivo bat para cada archivo que llegue a la carpeta que no quiero. Mis conocimientos son mínimos y sólo sé lo suficiente para ser peligroso.

Si XXXX.PDF, XXRX.PDF, XXLX.PDF llegan a la carpeta, necesito que sepa si llega XXXX.PDF, ejecute XXXX.bat únicamente. Si XXRX.PDF aterriza, ejecute XXRX.BAT únicamente, etc., etc.

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

### DEFINE ACTIONS AFTER A EVENT IS DETECTED

    $action = {Invoke-Item "D:\BATCH FILES\XXXXX.bat" -filter = "XXXXX.pdf"}    

### DECIDE WHICH EVENTS SHOULD BE WATCHED + SET CHECK FREQUENCY  
    $created = Register-ObjectEvent $watcher "Created" -Action $action
###    $changed = Register-ObjectEvent $watcher "Changed" -Action $action
###    $deleted = Register-ObjectEvent $watcher "Deleted" -Action $action
###    $renamed = Register-ObjectEvent $watcher "Renamed" -Action $action
    while ($true) {sleep 5}

Respuesta1

Los FileWatchers tienen peculiaridades,dependiendo de cómo se crean los archivos:

Es posible que observe en determinadas situaciones que un único evento de creación genera varios eventos creados que son manejados por su componente. Por ejemplo, si usa un componente FileSystemWatcher para monitorear la creación de nuevos archivos en un directorio y luego lo prueba usando el Bloc de notas para crear un archivo, es posible que vea dos eventos creados generados aunque solo se haya creado un archivo. Esto se debe a que el Bloc de notas realiza múltiples acciones del sistema de archivos durante el proceso de escritura. El Bloc de notas escribe en el disco en lotes que crean el contenido del archivo y luego los atributos del archivo. Otras aplicaciones pueden funcionar de la misma manera. Debido a que FileSystemWatcher monitorea las actividades del sistema operativo, se detectarán todos los eventos que activen estas aplicaciones.

Nota: El Bloc de notas también puede provocar otras generaciones de eventos interesantes. Por ejemplo, si usa ChangeEventFilter para especificar que desea observar solo los cambios de atributos y luego escribe en un archivo en el directorio que está observando usando el Bloc de notas, generará un evento. Esto se debe a que el Bloc de notas actualiza el atributo Archivado del archivo durante esta operación.

Entonces, en su caso, optaría por una simple comparación de directorios. Aquí está el script que monitoreará el directorio en busca de cambios y ejecutará archivos. Guarde este script como MonitorAndExecute.ps1. Acepta los siguientes argumentos:

  • Camino:carpeta a monitorear. Si no se especifica, se utiliza el directorio actual.
  • Filtrar:extensión de archivo para que coincida. El valor predeterminado es *, es decir, coincidir con todos los archivos.
  • Correr:extensión de archivo que se ejecutará cuando se encuentre un nuevo archivo. El valor predeterminado es bat.
  • recursivo:directorios recurrentes o no. El valor predeterminado es falso.
  • Intervalo:Tiempo en segundos para dormir entre escaneos de carpetas. El valor predeterminado es 5segundos.
  • Verboso:El script le dirá lo que está pasando a través de Write-Verbosemensajes.

Ejemplo (ejecutar desde la consola de PowerShell).

Supervise *.pdflos archivos en la carpeta D:\XXXX\XXXX, recurra, si se encuentra el nuevo archivo, ejecute el archivo con el mismo nombre base y extensión *.bat, sea detallado:

.\MonitorAndExecute.ps1 -Path 'D:\XXXX\XXXX' -Filter '*.pdf' -Run 'bat' -Recurse -Interval 10 -Verbose

MonitorAndExecute.ps1guion:

Param
(
    [Parameter(ValueFromPipelineByPropertyName = $true)]
    [ValidateScript({
        if(!(Test-Path -LiteralPath $_ -PathType Container))
        {
            throw "Input folder doesn't exist: $_"
        }
        $true
    })]
    [ValidateNotNullOrEmpty()]
    [string]$Path = (Get-Location -PSProvider FileSystem).Path,

    [Parameter(ValueFromPipelineByPropertyName = $true)]
    [string]$Filter = '*',

    [Parameter(ValueFromPipelineByPropertyName = $true)]
    [string]$Run = 'bat',

    [Parameter(ValueFromPipelineByPropertyName = $true)]
    [switch]$Recurse,

    [Parameter(ValueFromPipelineByPropertyName = $true)]
    [int]$Interval = 5
)

# Scriptblock that gets list of files
$GetFileSet = {Get-ChildItem -LiteralPath $Path -Filter $Filter -Recurse:$Recurse | Where-Object {!($_.PSIsContainer)}}

Write-Verbose 'Getting initial list of files'
$OldFileSet = @(. $GetFileSet)
do
{
    Write-Verbose 'Getting new list of files'
    $NewFileSet = @(. $GetFileSet)

    Write-Verbose 'Comaparing two lists using file name and creation date'
    Compare-Object -ReferenceObject $OldFileSet -DifferenceObject $NewFileSet -Property Name, CreationTime -PassThru |
        # Select only new files
        Where-Object { $_.SideIndicator -eq '=>' } |
            # For each new file...
            ForEach-Object {
                Write-Verbose "Processing new file: $($_.FullName)"
                # Generate name for file to run
                $FileToRun = (Join-Path -Path (Split-Path -LiteralPath $_.FullName) -ChildPath ($_.BaseName + ".$Run"))

                # If file to run exists
                if(Test-Path -LiteralPath $FileToRun -PathType Leaf)
                {
                    Write-Verbose "Running file: $FileToRun"
                    &$FileToRun
                }
                else
                {
                    Write-Verbose "File to run not found: $FileToRun"
                }
            }

    Write-Verbose 'Setting current list of files as old for the next loop'
    $OldFileSet = $NewFileSet

    Write-Verbose "Sleeping for $Interval seconds..."
    Start-Sleep -Seconds $Interval
}
while($true)

información relacionada