遵循的最重要编码方法之一是确保您了解并管理代码的每种“流动”方式。如果您将代码视为一种流程,它可以分支、返回到各个点,并遇到许多条件。
错误处理确保您设置“网”,或者在发生意外情况时,代码可以流向的默认位置。
让我们使用一个您可能会遇到的实际场景,处理 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 = 'Continue' $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/