Powershell 資料夾監控/批次執行

Powershell 資料夾監控/批次執行

我是 Powershell 新手。我找到了一個可以滿足我需要的腳本。

我正在尋找的是一個用於監視資料夾中特定檔案名稱/類型的腳本。根據檔案名稱/類型,我希望它執行某個批次檔來執行伺服器實用程式的命令。

我到底如何實現這一點。但是,我需要過濾它並讓它根據檔案名稱啟動不同的 bat 檔案。我目前擁有的,它將為位於我不想要的資料夾中的每個檔案調用bat 檔案。我的知識很少,只知道會帶來危險。

如果 XXXX.PDF、XXRX.PDF、XXLX.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.
  • 遞迴:是否遞歸目錄。預設為 false。
  • 間隔:資料夾掃描之間的睡眠時間(以秒為單位)。預設值為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)

相關內容