Powershell:如何删除多个&有例外的目录?

时间:2013-07-11 20:02:13

标签: windows powershell recursion filesystems powershell-v2.0

设置

我的文件夹结构如下:

C:\RootFolder
            \file1.txt
            \file2.txt
            \license.txt
            \Settings
                     \fileA.txt
                     \fileB.txt
                     \settings.txt
            \OtherFolders

目标

删除除license.txt和settings.txt以外的所有文件。

我想最终只留下以下内容:

  C:\RootFolder
                \license.txt
                \Settings
                         \settings.txt

远程脚本

$exclude = @('license.txt', 'settings.txt')
Get-ChildItem C:\RootFolder -recurse -exclude $exclude | foreach ($_) {remove-item $_.fullname -recurse:$false}

问题

即使我具体指定-recurse:$ false,它总是为每个文件夹生成一条消息,指示“未指定递归”并说它将删除所有子项。

此后,license.txt文件仍然存在,但settings.txt文件(在子目录中)没有。

2 个答案:

答案 0 :(得分:2)

几乎在我发布后,答案就出现了 - 我只能找到文件,而不是目录。

由于我使用的是PowerShell 2.0,因此无法使用PowerShell 3中新增的-File属性。相反,我必须检查每个对象以查看它是否为容器。

解决方案:

$exclude = @('license.txt', 'settings.txt')

Get-ChildItem C:\RootFolder -recurse -exclude $exclude | Where-Object {!($_.PSIsContainer)} | foreach ($_) {remove-item $_.fullname}

这完美地实现了我所需要的。

改善解决方案

感谢这里的一些评论/帖子,有一些更优雅的方式让我更多地了解了powershell:

  • Remove-Item可以从管道中获取命令。不需要foreach。
  • Where-Object可以缩短为“?”
  • Get-ChildItem可缩短为“gci”(别名)
  • 在Foreach之后我们不需要($ _)。 Foreach自动理解。
  • 如果我们想将排除列在一行上,我们可以通过右内联数组
  • 来完成

鉴于这些,适合单线的优雅解决方案将是:

gci C:\RootFolder -Recurse -Exclude @('license.txt', 'settings.txt') | ? { ! $_.PSIsContainer } | Remove-Item -Force

答案 1 :(得分:1)

您的代码效果很好。

只是一个单行,所以我们可以采取另一种方式:

Get-ChildItem C:\RootFolder -recurse | Where-Object {!($_.PSIsContainer)} | Foreach { if ( $_.Name -ne "license.txt" -and $_.Name -ne "settings.txt") {remove-item $_.FullName -force}}

如果需要排除很多文件,那么这一个内容不会扩展 - 在这种情况下我将使用您的代码:)

顺便提一下@Sean Killeen:foreach之后是否有($ _)?听起来你正在使用Foreach-Object Cmdlet而不是Foreach构造。我的理解是在“foreach-object”之后我们不需要Cmdlet($ sometingElse中的$)。但是在Foreach构造中我们需要($ something $ somethingElse)。如果我错了,请纠正我。