我是 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)