Powershell 폴더 모니터/일괄 실행

Powershell 폴더 모니터/일괄 실행

저는 Powershell을 처음 사용합니다. 내가 필요한 것과 작동하는 스크립트를 찾았습니다.

내가 찾고 있는 것은 특정 파일 이름/유형에 대해 폴더를 모니터링하는 스크립트입니다. 파일 이름/유형에 따라 특정 배치 파일을 실행하여 서버 유틸리티에 대한 명령을 실행하고 싶습니다.

정확히 어떻게 이것을 달성할 수 있습니까? 이 스크립트를 발견하고 폴더에 있는 PDF와 같은 파일 하나에 대해 batfile을 실행하기 위한 호출 항목을 추가했습니다. 그러나 이를 필터링하고 파일 이름에 따라 다른 bat 파일을 실행해야 합니다. 내가 현재 가지고 있는 것은 내가 원하지 않는 폴더에 있는 각 파일에 대해 bat 파일을 호출합니다. 나의 지식은 미미하며 위험할 만큼만 알고 있습니다.

XXXX.PDF, XXRX.PDF, XXXX.PDF가 폴더에 도달한 경우 XXXX.PDF가 있는지 확인하려면 XXXX.bat만 실행해야 합니다. XXRX.PDF가 실행되면 XXRX.BAT만 실행합니다.

### 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}

답변1

FileWatchers에는 특이한 점이 있습니다.파일 생성 방법에 따라:

특정 상황에서는 단일 생성 이벤트가 구성 요소에서 처리하는 여러 Created 이벤트를 생성하는 것을 볼 수 있습니다. 예를 들어 FileSystemWatcher 구성 요소를 사용하여 디렉터리의 새 파일 생성을 모니터링한 다음 메모장을 사용하여 파일을 생성하여 테스트하면 단일 파일만 생성되었음에도 생성된 두 개의 Created 이벤트를 볼 수 있습니다. 이는 메모장이 쓰기 프로세스 중에 여러 파일 시스템 작업을 수행하기 때문입니다. 메모장은 파일 내용과 파일 속성을 생성하는 일괄 작업으로 디스크에 기록합니다. 다른 응용 프로그램도 동일한 방식으로 수행될 수 있습니다. FileSystemWatcher는 운영 체제 활동을 모니터링하므로 이러한 응용 프로그램이 실행하는 모든 이벤트가 선택됩니다.

참고: 메모장은 다른 흥미로운 이벤트 생성을 유발할 수도 있습니다. 예를 들어 ChangeEventFilter를 사용하여 속성 변경만 감시하도록 지정한 다음 메모장을 사용하여 감시 중인 디렉터리의 파일에 쓰면 이벤트가 발생합니다. 이는 이 작업 중에 메모장이 파일의 보관 속성을 업데이트하기 때문입니다.

따라서 귀하의 경우에는 일반 디렉토리 비교를 사용하겠습니다. 다음은 디렉터리의 변경 사항을 모니터링하고 파일을 실행하는 스크립트입니다. 이 스크립트를 MonitorAndExecute.ps1. 다음 인수를 허용합니다.

  • :모니터링할 폴더입니다. 지정하지 않으면 현재 디렉터리가 사용됩니다.
  • 필터:일치하는 파일 확장자. 기본값은 입니다 *. 즉, 모든 파일과 일치합니다.
  • 달리다:새 파일이 발견되면 실행할 파일 확장자입니다. 기본값은 입니다 bat.
  • 재귀:반복 디렉토리 여부. 기본값은 거짓입니다.
  • 간격:폴더 검색 간 대기 시간(초)입니다. 기본값은 5초입니다.
  • 말 수가 많은:스크립트는 메시지를 통해 무슨 일이 일어나고 있는지 알려줄 것입니다 Write-Verbose.

예(PowerShell 콘솔에서 실행)

*.pdf폴더의 파일을 모니터링 D:\XXXX\XXXX하고 반복하여 새 파일이 발견되면 동일한 기본 이름과 확장자를 가진 파일을 실행하고 *.bat자세한 정보를 표시합니다.

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

MonitorAndExecute.ps1스크립트:

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)

관련 정보