遵循的最重要的編碼方法之一是確保您知道並管理代碼的每一種“流動”方式。如果您將代碼視為一種流,它可以分支、返回到各個點,並遇到許多條件。
錯誤處理確保您設置“網”或當發生意外情況時,代碼可以流向的預設位置。
讓我們使用一個您可能會遇到的真實情境,處理 PowerShell 的錯誤處理。
建立檔案清理的初始腳本
我們需要清理一些舊檔案。我們的檔案伺服器已經存在很久了,我們需要清理一些空間。管理層已決定刪除所有超過指定天數的檔案。我們需要建立一個腳本,遞歸搜索一個資料夾,找到所有超過一定天數的檔案並刪除它們。
這項任務聽起來簡單,但這是錯誤處理部分,所以您知道某些事情會出錯!
讓我們開始了解錯誤處理,首先建立沒有錯誤處理的情境演示腳本來展示錯誤處理所解決的問題。
-
首先,打開一個新的 VS Code 標籤。
由於我們現在只是嘗試幾件事情,我們不會立即保存腳本。暫時告訴 VS Code 您將要編寫一些 PowerShell。
按 Ctrl-Shift-P,輸入 ‘lang’,選擇選擇語言模式,輸入 ‘power’,然後選擇 PowerShell。現在 VS Code 知道您將要編寫 PowerShell。
-
接下來,將問題分解為任務,首先解決最明顯的任務。
在這個例子中,這個任務是提出一個命令來讀取目錄中的文件。
Get-ChildItem -Path C:\OldForgottenFolder
-
Get-ChildItem
也會返回我們不需要的目錄,因此我們將其限制為僅返回文件。Get-ChildItem -Path C:\OldForgottenFolder -File
-
如果這些子目錄中有文件,我們需要使用
Recurse
來獲取它們。Get-ChildItem -Path C:\OldForgottenFolder -File -Recurse
-
現在我們已經有了命令和參數,它返回所有檔案。我們只需要找到超過某個天數的檔案。
由於
Get-ChildItem
返回每個檔案的LastWriteTime
物件屬性,我們必須根據該屬性進行過濾。我們將使用Where
過濾器來尋找LastWriteTime
早於指定日期的檔案。(Get-ChildItem -Path C:\OldForgottenFolder -File -Recurse).Where{$_.LastWriteTime -le ?????}
-
日期需要是動態的,因為今天的「舊」與明天的「舊」會有所不同。
註解掉前一行,因為我們在某個時候需要它,然後再弄清楚日期的問題。
## (Get-ChildItem -Path C:\\OldForgottenFolder -File -Recurse).Where{$_.LastWriteTime -le ?????} $Now = Get-Date $Now
-
現在我們有了今天的日期,讓我們找出今天之前特定天數的日期。我暫時在這裡放入
30
,因為我知道有些檔案的修改日期已超過五天,以便進行初步測試。## (Get-ChildItem -Path C:\\OldForgottenFolder -File -Recurse).Where{$_.LastWriteTime -le ?????} $Now = Get-Date $LastWrite = $Now.AddDays(-30) $LastWrite
-
完成!讓我們把這些組合起來。
$Now = Get-Date $LastWrite = $Now.AddDays(-30) (Get-ChildItem -Path C:\OldForgottenFolder -File -Recurse).Where{$_.LastWriteTime -le $LastWrite}
我們現在有一個小腳本,可以找到目錄中所有比特定天數更舊的檔案。
-
接下來,我們必須添加刪除這些舊檔案的功能。這使用
Remove-Item
cmdlet和管道非常簡單。$Now = Get-Date $LastWrite = $Now.AddDays(-30) (Get-ChildItem -Path C:\OldForgottenFolder -File -Recurse).Where{$_.LastWriteTime -le $LastWrite} | Remove-Item
-
完成!但是等一下,我不知道它移除了哪些檔案。還有一些錯誤,我們會在幾分鐘內處理。讓我們添加一些基本功能。
$VerbosePreference = '繼續' $Now = Get-Date $LastWrite = $Now.AddDays(-30) $oldFiles = (Get-ChildItem -Path C:\OldForgottenFolder -File -Recurse).Where{$_.LastWriteTime -le $LastWrite} foreach ($file in $oldFiles) { Remove-Item -Path $file.FullName Write-Verbose -Message "成功移除 [$($file.FullName)]。" }
-
你需要包含一個像這樣的循環,以便對每個檔案執行某種代碼。在這裡,我們不使用管道,而是將所有找到的檔案放在一個
oldFiles
變數中,這是一個檔案物件的數組。然後我們像之前一樣對每個檔案執行Remove-Item
,但這次包含一條詳細訊息告訴我們正在移除哪個檔案。 -
現在讓我們運行這段代碼,看看會發生什麼。
您現在可以通過詳細訊息看到它刪除了一些檔案。我們現在擁有的代碼是創建腳本所需的核心內容。讓我們在接下來的部分從這個代碼創建一個真正的腳本。
最大化靈活性和可重用性,使用參數
您已經構建了腳本,但它仍然有潛力變得靈活和可重用。怎麼做?參數將允許我們指定目錄和我們想要針對的檔案年齡,使腳本更具靈活性。
-
在我們進一步之前,讓我們保存我們的工作。將其命名為 Remove-FileOlderThan.ps1。
請注意使用破折號的動詞/名詞格式。如果可能,請始終以與 PowerShell 命令相同的方式創建腳本名稱,以保持一致性和可讀性。
-
首先,腳本旨在可重用。你可能會想在不同的目錄和不同的年齡上使用這個腳本。我們需要引入一些參數。為此,我們要弄清楚什麼會改變。目錄和天數。明白了。
param ( [Parameter(Mandatory)] [string]$FolderPath,
[Parameter(Mandatory)] [int]$DaysOld
)
$Now = Get-Date
$LastWrite = $Now.AddDays(-30)
$oldFiles = (Get-ChildItem -Path C:\OldForgottenFolder -File -Recurse).Where{$_.LastWriteTime -le $LastWrite}
foreach ($file in $oldFiles) {
Remove-Item -Path $file.FullName
Write-Verbose -Message "成功移除 [$($file.FullName)]。"
}在頂部添加一個
param
區塊,並將每個參數定義為必需,因為我們必須有一個路徑和數字才能使腳本正常運行。此外,這裡指定類型也是最佳實踐。 -
用參數值替換之前代碼中的靜態項目。
param ( [Parameter(Mandatory)] [string]$FolderPath,
[Parameter(Mandatory)] [int]$DaysOld
)
$Now = Get-Date
$LastWrite = $Now.AddDays(-$DaysOld)
$oldFiles = (Get-ChildItem -Path $FolderPath -File -Recurse).Where{$_.LastWriteTime -le $LastWrite}
foreach ($file in $oldFiles) {
Remove-Item -Path $file.FullName
Write-Verbose -Message "成功移除 [$($file.FullName)]。"
} -
現在讓我們運行這個腳本,看看會發生什麼。
C:\Scripts\Remove-FileOlderThan.ps1 -FolderPath C:\OldForgottenFolder -DaysOld 30 -Verbose
您可以看到我們必須將文件夾的路徑和天數作為參數進行指定。使用
Verbose
參數來查看Write-Verbose
行。PowerShell 以與之前完全相同的方式運行了腳本,但現在我們有了一個可以用於任何目錄或任何文件年齡的參數化腳本!
查看輸出時,我們確實出現了一些紅色文本。要麼您沒有權限,要麼文件是只讀的。但是它在什麼文件上失敗了呢?如何確保那些文件也被刪除呢?
結論
在本教程中,我們構建了一個腳本來清理目錄中的舊文件,通過添加參數來確保靈活性。雖然腳本按預期工作,但我們看到錯誤處理尚未解決,這在處理現實場景時至關重要。
隨著我們的進展,增加錯誤管理將使我們能夠處理問題,例如cmdlet拋出錯誤或文件不可訪問,幫助我們避免腳本終止並提供有關問題的詳細見解。
敬請期待下一個演示!PowerShell 101:終止性錯誤、非終止性錯誤和 Try/Catch。
Source:
https://adamtheautomator.com/powershell-file-cleanup-script/