当前位置:网站首页 > 更多 > 玩电脑 > 正文

[玩转系统] 探索 PowerShell 使用 Remove-Item 和 WMI 删除文件

作者:精品下载站 日期:2024-12-14 13:05:14 浏览:14 分类:玩电脑

探索 PowerShell 使用 Remove-Item 和 WMI 删除文件


管理服务器和系统时,维护可用磁盘空间至关重要。作为管理员,您不希望不知道“磁盘已满”的情况。为了确保您没有任何问题,您应该学习如何使用 PowerShell 删除文件!

在本文中,您将了解使用 PowerShell 从系统中删除文件的各种方法。

让我们开始吧!

先决条件

本文介绍了使用 PowerShell 的示例,如果您打算继续学习,则需要以下内容。

  • 运行 Windows 10 或更高版本的计算机。
  • Windows PowerShell 5.1 或 PowerShell 7.0
  • 脚本编辑器,例如 Visual Studio CodeAtomNotepad++

使用Remove-Item Cmdlet 删除文件

当您只需要使用 PowerShell 删除文件时,您可能会立即了解 Remove-Item cmdlet。此 cmdlet 是使用 PowerShell 删除文件的事实上的标准。

Remove-ItemGet-ChildItem cmdlet 结合使用来读取文件和文件夹以及强大的 PowerShell 管道确实可以让事情变得轻而易举。

相关:Get-ChildItem:列出文件、注册表、证书等

您是否知道 Remove-Item cmdlet 有一个名为 del 的别名?在 PowerShell 中工作时,使用 Remove-Itemdel 将运行相同的命令。

使用 PowerShell 删除文件

第一个最有用的示例是最基本的,即删除单个文件。要删除单个文件,只需使用以下命令。下面的代码删除文件C:\temp\random.txt

Remove-Item -Path C:\temp\random.txt

在 PowerShell 中运行上面的代码不会在屏幕上显示任何内容,除非遇到错误。

使用PowerShell删除文件夹中的所有文件

在此示例中,以下代码删除文件夹中的所有文件。 Get-ChildItem cmdlet 的目标是带有 -Path 参数的 C:\temp-File 参数指示要包含的唯一项目类型是文件。 Get-ChildItem 忽略文件夹。

Get-ChildItem -Path C:\temp -File | Remove-Item -Verbose

输出应类似于下面的屏幕截图。

[玩转系统] 探索 PowerShell 使用 Remove-Item 和 WMI 删除文件

使用PowerShell递归删除所有文件

前面的示例仅删除了 C:\temp 文件夹中的文件。如果您还需要删除每个子目录中的文件,则需要将 -Recurse 开关添加到 Get-ChildItem cmdlet 以递归获取所有文件。

Get-ChildItem -Path C:\temp -File -Recurse | Remove-Item -Verbose

运行上述代码会强制 PowerShell 查看所有子文件夹并检索所有文件列表。下面的输出显示代码能够删除顶部文件夹中的文件;但是,它无法检索子文件夹中的文件。

[玩转系统] 探索 PowerShell 使用 Remove-Item 和 WMI 删除文件

解决长路径问题

上面显示的错误表明 PowerShell“无法找到路径的一部分”。该错误表明 cmdlet 尝试访问的路径不存在 - 这是误导性的。

在本例中,错误是因为 Get-ChildItem 尝试读取的路径超过了 260 个字符的最大路径长度

下面的屏幕截图显示该路径或目录及其子目录存在,并且一个名为 InTooDeep.txt 的文本文件位于最底部的子目录中。构成嵌套目录名称的所有字符的组合会产生长路径问题。

[玩转系统] 探索 PowerShell 使用 Remove-Item 和 WMI 删除文件

在 Windows PowerShell 5.1 中,有一个解决长路径名问题的方法。解决方法是使用 Unicode 版本的路径。不要指定这样的路径 - C:\temp,而是使用这样的 Unicode 版本 - '\?\C:\temp' 对于位于本地的文件夹,或者'\?\UNC\\Temp'(如果文件夹位于 UNC 路径中)。

Get-ChildItem -Path '\?\C:\temp' -File -Recurse | Remove-Item -Verbose

使用上面针对长路径名的修改后的代码,下面的输出显示 PowerShell 成功读取深度嵌套的路径名并删除该文件。

[玩转系统] 探索 PowerShell 使用 Remove-Item 和 WMI 删除文件

请注意,长路径名问题不会影响 PowerShell 7.0。使用 PowerShell 7.0,无需使用 Unicode 版本的路径,因为它已经内置了对长路径名的支持。

如果还需要删除文件夹,只需从 Get-ChildItem cmdlet 中删除 -File 参数,PowerShell 就会删除所有项目,包括文件和文件夹。

使用 PowerShell 删除早于 x 天的文件

磁盘空间管理的另一个典型示例是删除早于特定天数的文件。此示例对于删除旧日志文件(如 IIS Web 服务器生成的日志文件)以释放磁盘空间非常有用。

在此示例中,c:\temp 中存在超过 14 天的文件。使用下面的脚本,将显示 c:\temp 中每个文件的 NameCreationTImeAgeInDays

Get-ChildItem c:\temp | Select-Object Name,CreationTime,@{n='AgeInDays';e={(New-TimeSpan -Start $PSItem.CreationTime).Days}}

正如您在下面的屏幕截图中看到的,有 15 天、7 天和 0 天的文件。

[玩转系统] 探索 PowerShell 使用 Remove-Item 和 WMI 删除文件

现在您知道了要删除的文件,您可以创建一个脚本来仅删除早于特定天数(在本例中为早于 14 天)的文件。

在下面的示例脚本中,C:\tempCreationTime 值早于设置阈值的文件将被删除。

第一行定义 Get-ChildItem 搜索的路径。该路径保存在 $path 变量中。然后,第二行是指定阈值的地方。 $threshold 的值是要删除的文件必须存在的期限(以天为单位)。

$threshold 变量之后的下一行代码将:

  • 获取位于 $path 变量中指定的文件夹中的文件集合。在此示例中,路径为C:\temp。
  • 过滤输出以仅包含 CreationTime 值早于 $threshold 变量中保存的天数的文件。在此示例中,阈值是 14 天。
  • 将过滤后的文件列表通过管道传递给 Remove-Item 值以执行这些文件的删除。
$path = 'C:\Temp'
$threshold = 14
Get-ChildItem -Path $path -File | Where-Object {$PSItem.CreationTime -lt (Get-Date).AddDays(-$threshold)} |Remove-Item -Verbose

当您运行上面的代码时,您将看到如下所示的输出。

[玩转系统] 探索 PowerShell 使用 Remove-Item 和 WMI 删除文件

请注意,从上面的屏幕截图中,根据详细消息,脚本仅删除了 5 个超过 14 天的文件。要确认 14 天以上的文件仍然存在,请运行以下代码以再次列出它们。

Get-ChildItem c:\temp | Select-Object Name,CreationTime,@{n='AgeInDays';e={(New-TimeSpan -Start $PSItem.CreationTime).Days}}

下面的结果证实 Remove-Item 没有删除较新的文件。

[玩转系统] 探索 PowerShell 使用 Remove-Item 和 WMI 删除文件

使用PowerShell匹配和删除文件模式

删除所有文件,无论名称、类型或扩展名如何,并不总是最好的方法。有时,您需要在删除过程中显式排除或包含某些文件。

下面的下一个示例显示如何删除与 *.LOG 文件名匹配的文件。一种方法是直接使用 Remove-Item cmdlet 并结合使用 -Include 参数,如下所示。

Remove-Item -Path C:\temp\* -Include *.log

另一种方法也许是谨慎的方法是首先使用 Get-ChildItem 来收集要删除的文件列表。只有当您对要删除的文件列表感到满意时,您才可以最终将集合通过管道传输到 Remove-Item cmdlet。

例如,下面的代码获取 c:\temp 中的 *.LOG 文件。

Get-ChildItem -Path C:\temp\* -Include *.log

上述代码的结果是,Get-ChildItem 返回与 *.LOG 文件名匹配的文件列表。

[玩转系统] 探索 PowerShell 使用 Remove-Item 和 WMI 删除文件

但是,如果您想排除名称中包含数字 5 的文件怎么办?您可以通过添加 -Exclude 参数来实现此目的,如下代码所示。

Get-ChildItem -Path C:\temp\* -Include *.log -Exclude *5*

由于您排除了编号为 5 的文件,因此现在的结果有所不同。具体来说,文件 File_5.log 不再出现在列表中,如下所示。

[玩转系统] 探索 PowerShell 使用 Remove-Item 和 WMI 删除文件

当您对代码创建的文件集合感到满意时,您可以将文件集合通过管道传输到 Remove-Item cmdlet 以最终删除这些文件。

Get-ChildItem -Path C:\temp\* -Include *.log -Exclude *5* | Remove-Item -Verbose

运行最终代码后,您将实现仅删除所选文件的目标。

[玩转系统] 探索 PowerShell 使用 Remove-Item 和 WMI 删除文件

在 PowerShell 中使用 WMI 删除文件

现在您已经很好地了解了如何使用常见的 Remove-Item cmdlet 来删除文件,接下来让我们进入更高级的用例;使用 WMI。

PowerShell 附带对 WMI 的支持。对 WMI 的支持意味着可以从 PowerShell 内调用 WMI 查询和方法。是的,WMI 不仅仅适用于管理员在 Windows 早期使用的 Visual Basic 脚本。

Microsoft 在 PowerShell 3.0 中发布了特定于 WMI 的 CIM cmdlet。用于删除文件的 CIM cmdlet 是 Get-CimInstanceInvoke-CimMethod

使用 PowerShell 和 WMI 删除文件

此示例假设您知道要删除的特定文件的路径。具有 Cim_DataFile 类的 Get-CimInstance cmdlet 用于检索有关要删除的文件的信息,该文件为 C:\Temp\random.txt

$file2delete = Get-CimInstance -ClassName Cim_DataFile -Filter "Name = 'C:\Temp\random.txt'"
 $file2delete

在上面的代码中,-Filter 参数接受 WQL 格式查询。使用 WQL 要求转义一些字符,包括反斜杠。并且,由于 WQL 转义字符也是反斜杠,导致出现双反斜杠字符 - \

运行上面的代码会产生如下演示所示的结果。有关C:\Temp\random.txt的信息保存到$file2delete变量中

现在已检索到文件 C:\Temp\random.txt 的信息,$file2delete 变量中的结果对象可以通过管道传输到 Invoke- CimMethod cmdlet。 Invoke-CimMethod cmdlet 有一个名为 -Name 的参数,它表示 Cim_DataFile 类的方法名称。

$file2delete | Invoke-CimMethod -Name Delete

正如您在下面的屏幕截图中看到的,ReturnValue 显示 0,这意味着命令成功。

[玩转系统] 探索 PowerShell 使用 Remove-Item 和 WMI 删除文件

要了解可能的 ReturnValue 代码,请参阅此链接 - CIM_DataFile 类的删除方法

此外,下面的屏幕截图显示,运行 Invoke-CimMethod Delete() 方法后,CIM 仅删除了 C:\Temp\random.txt 文件。它没有删除其他文件。

[玩转系统] 探索 PowerShell 使用 Remove-Item 和 WMI 删除文件

使用PowerShell和WMI删除文件夹中的所有文件

在下一个示例中,将向您展示如何使用 PowerShell 和 WMI 删除文件夹中的所有文件。将使用上一示例中使用的相同 cmdlet,即 Get-CimInstanceInvoke-CimMethod。但是,这一次,WQL 查询将检索文件夹中的所有文件,而不是仅检索一个特定文件。

在接下来的代码中,Get-CimInstance cmdlet 检索位于 C:\temp 中的所有文件。如下所示,查询会筛选 Cim_DataFile 类的 DrivePath 属性。

$file2delete = Get-CimInstance -ClassName Cim_DataFile -Filter "Drive = 'c:' AND Path = '\temp\'"

运行上面的代码会将检索到的有关 C:\temp 中文件的信息保存在 $file2delete 变量中。查看 $file2delete 变量的值会显示以下输出。

[玩转系统] 探索 PowerShell 使用 Remove-Item 和 WMI 删除文件

现在,存储在 $file2delete 变量中的值可以通过管道传输到 Invoke-CimMethod 以删除 c:\temp 中的所有文件。

$file2delete | Invoke-CimMethod -Name Delete

请记住,ReturnValue 代码为 0 表示成功,并且对于调用删除方法的每个文件都将有其自己的 ReturnValue 代码。

[玩转系统] 探索 PowerShell 使用 Remove-Item 和 WMI 删除文件

使用PowerShell和WMI按扩展名删除文件

您在前面的示例中已经了解了如何删除文件夹中的所有文件(无论扩展名如何)。但是,您还可以根据扩展名控制删除哪些文件。

您会在下面的代码中注意到,这次查询添加了一个条件(Name LIKE '%.log)。此添加的条件意味着仅返回与 .LOG 扩展名匹配的文件。百分号 (%) 是 WQL LIKE 运算符,表示“零个或多个字符的字符串”。在编程术语中,% 相当于通配符,即星号 (*) 字符。

$file2delete = Get-CimInstance -ClassName cim_datafile `
-Filter "Drive = 'c:' AND Path = '\temp\' AND Name LIKE '%.log'"

$file2delete | Invoke-CimMethod -Name Delete

下面的演示显示,在执行上述代码之前,有 9 个 *.LOG 文件,只有 1 个 *.TXT 文件。代码运行完毕后,*.LOG 文件将被删除,*.TXT 文件是文件夹中剩下的唯一文件。

比较 WMI 和删除项目

到目前为止,在本教程中,您已经大致了解了如何使用 PowerShell 删除文件。您已经了解了 Remove-Item 和 WMI。两者执行相似的功能但有很大不同。

您应该使用哪种方法来删除文件; 删除项目还是WMI?

使用 PowerShell 中的内置 cmdlet(例如 Get-ChildItemRemove-Item)检索和删除文件比使用 WMI 快得多。

下面的示例显示了使用 WMI 和内置 PowerShell cmdlet 获取 C:\windows\web 目录及其子目录下的文件列表时的比较。

## List all files in C:\Windows\Web\ recursively using Get-ChildItem
Measure-Command { Get-ChildItem C:\Windows\Web\ -Recurse}

## List all files in C:\Windows\Web\ recursively using Get-CimInstance and WMI Query
Measure-Command { Get-CimInstance -ClassName Cim_DataFile -Filter "Drive = 'c:' AND Path = '\windows\web\%'"}

当您在 PowerShell 中运行上面的代码时,您将看到类似以下的输出。

[玩转系统] 探索 PowerShell 使用 Remove-Item 和 WMI 删除文件

正如您从上面显示的输出中看到的,使用 Get-CimInstance 列出 C:\windows\web 中的文件几乎花费了十倍的时间比 Get-ChildItem 完成所需的时间还要长!

另外,您是否注意到 Get-ChildItem 行比 Get-CimInstance 短得多?使用 Get-ChildItem 不仅可以加快执行速度,而且还可以受益于更简洁的代码。

下一步

在本文中,您了解了使用 PowerShell 通过内置 cmdlet 和 WMI/CIM 删除文件的两种不同方法。

请注意,您应该始终使用 Get-ChildItemRemove-Item cmdlet 来删除文件。与使用 WMI 相比,这些内置 cmdlet 使用起来更灵活、更容易且更快。

尝试想出一个可以为您执行磁盘空间管理的脚本。当然,已经存在一些用于此目的的脚本;无论如何,请使用它们作为参考,但如果您愿意练习和学习,您应该尝试创建自己的。

进一步阅读

  • CIM_DataFile 类
  • 最大路径长度限制
  • 我应该将 CIM 或 WMI 与 Windows PowerShell 结合使用吗?

您需要 登录账户 后才能发表评论

取消回复欢迎 发表评论:

关灯