删除所有文件和文件夹,但排除一个子文件夹。

65

我有一个文件夹,我需要删除其中所有的文件和文件夹,除了一小部分文件和文件夹。

我已经可以排除一些文件,但不知道如何排除一个文件夹及其内容。

下面是文件夹结构:

|-C:\temp
 \-C:\temp\somefile.txt
 \-C:\temp\someotherfile.txt
| |-C:\temp\foldertodelete
   \-C:\temp\foldertodelete\file1.txt
| |-C:\temp\foldertokeep
|  \-C:\temp\foldertokeep\file2.txt

我想保留somefile.txt和foldertokeep文件夹及其内容。

这是我现在拥有的:

Get-ChildItem -Path  'C:\temp' -Recurse -exclude somefile.txt | Remove-Item -force -recurse

这确实不会删除 somefile.txt。有没有办法将文件夹foldertokeep及其内容从删除列表中排除?


我这里缺少什么?这个代码对我来说似乎是可以工作的Get-ChildItem -Path 'C:\temp' -Recurse -exclude somefile.txt, foldertokeep | Remove-Item -force -recurse - KCD
13个回答

68
Get-ChildItem -Path  'C:\temp' -Recurse -exclude somefile.txt |
Select -ExpandProperty FullName |
Where {$_ -notlike 'C:\temp\foldertokeep*'} |
sort length -Descending |
Remove-Item -force 

-recurse开关在Remove-Item上不能正常工作(它会尝试在删除文件夹中的所有子项之前删除文件夹)。按fullname长度降序排序可以确保删除文件夹中的所有子项之前不会删除任何文件夹。


3
复杂而精彩,典型的 PowerShell 粗糙特性。我希望它能不断发展。谢谢。 - moodboom
1
我必须在最后一行添加一个额外的[-Recurse]参数才能使脚本在不提示的情况下继续执行。 - moodboom
“sort length -Descending” 是什么意思? - KyleMit
这将按照文件和目录全名的长度进行排序,按降序排列。这确保在删除目录之前,先删除目录的所有子项。 - mjolinor

34

选择需要保留的内容以外的所有内容,并将其传输到删除命令。

假设您有这些文件夹

C:.
├───delme1
│   │   delme.txt
│   │
│   └───delmetoo
├───delme2
├───keepme1
│       keepmetoo.txt
│
└───keepme2

删除除了保留keepme1和keepme2文件夹之外的所有内容。

Get-ChildItem -Exclude keepme1,keepme2 | Remove-Item -Recurse -Force

其他解决方案也不错,但我发现这个易于理解和记忆。


1
我喜欢这个解决方案,你只需要一个递归:Get-ChildItem -Exclude folder1,folder2 | Remove-Item -Recurse -Force - AxelWass
太对了@AxelWass,比XD更好的解决方案。 - guillem

33

在PowerShell 3.0及以下版本中,您可以尝试简单地执行以下操作:

Remove-Item -recurse c:\temp\* -exclude somefile.txt,foldertokeep

除非我漏掉了某些参数,否则这似乎可以解决问题...

编辑:请查看下面的评论,自从PS3之后Remove-Item的行为已经改变,这个解决方案似乎不再适用。


19
我曾经在PowerShell 3.0下执行这个动作,效果非常好。但是我刚刚发现,在PowerShell 4.0版本中该行为已经改变了。例如,假设您在同一父目录下有目录"a"和"b",并且在目录"a"下有文件"c.txt"。如果您在父目录下运行"rm .\* -Recurse -Exclude a"命令,则在PS 4中,c.txt文件将被删除。而在PS 3中则不会。我在想这是否是PS 4的一个错误,因为在我看来这是没有意义的。 - Jon Miller
3
@JonMiller 我也遇到了同样的问题。从PS2迁移到PS4后,发现我们系统中的一些重要目录被删除了。幸好备份还在 :) - Brian Chavez
评论中有很棒的信息。也许根据PowerShell版本可能会出现不同的行为,所以这可能不是一种安全的技术? - JohnB
11
它排除了该文件夹,但遗憾的是没有排除其内容。 - jenson-button-event
刚刚再次查看了一下。它看起来比@JonMiller提到的还要糟糕。根据我的实验,当使用-recurse时,-exclude仅应用于根目录。这绝对看起来像一个错误...编辑:算了,情况比那更奇怪。 - Poorkenny

8
我使用以下代码,只需将第一行中的“-Recurse”删除即可保留排除文件夹列表下的所有文件和子文件夹。
   Get-ChildItem -Path "PATH_GOES_HERE" -Exclude "Folder1", "Folder2", "READ ME.txt" | foreach ($_) {
       "CLEANING :" + $_.fullname
       Remove-Item $_.fullname -Force -Recurse
       "CLEANED... :" + $_.fullname
   }

7

是的,我知道这是一个旧线程。我在Powershell 5中无法让上面任何一个答案起作用,所以这就是我找到的解决方法:

Get-ChildItem -Path $dir -Exclude 'name_to_ignore' |
ForEach-Object {Remove-Item $_ -Recurse }

这将把-Recurse移到Remove-Item处,而不是在找到项目的地方使用。

6
根据MSDNRemove-Item命令在使用-exclude参数时存在已知问题。请改用此变体。
Get-ChildItem * -exclude folderToExclude | Remove-Item

1
注意:<folderToExclude>应该只是folderToExclude的名称,没有尾随的\*,否则它将在第1级(仅限第1级,不超出)留下空目录。 - Ujjwal Singh

4
我遇到了这个问题,并找到了一个适合我的一行命令。它将删除目录中的所有文件和文件夹,同时保留“排除”列表中的任何内容。此外,它是静默的,如果某些文件是只读或正在使用,则不会返回错误。
@powershell Remove-item C:\Random\Directory\* -exclude "MySpecialFolder", "MySecondSpecialFolder" -force -erroraction 'silentlycontinue'

4

这也会帮助某人...

如果在之前没有定义或为空的情况下添加一个名为PATH_GOES_HERE的变量,可能会导致用户目录(如果脚本以管理员身份运行,则为C:\ windows \ system32)中的递归删除。我通过艰难的方式发现了这一点,不得不重新安装Windows。

自己试试吧!(下面仅将文件目录输出到test.txt中)

Get-ChildItem -Path $dir2 -Recurse -Exclude "Folder1 ", FileName.txt | foreach ($_) {
$_.fullname >> C:\temp\test.txt
}

2
我用的这个,对我来说完美无误。
Get-ChildItem -Path 'C:\Temp\*' -Recurse | Where-Object {($_.FullName -notlike "*windirstat*") -and ($_.FullName -notlike "C:\Temp\GetFolderSizePortable*")} | Remove-Item -Recurse

1
如果您的路径包含正则表达式特殊字符,则需要使用-LiteralPath选项,该选项不允许使用管道。在这种情况下,正确的解决方案如下:
    Remove-Item -force -LiteralPath(    
    Get-ChildItem -Path  'C:\temp' -Recurse -exclude somefile.txt |
    Select-Object -ExpandProperty FullName |
    Where-Object { $_ -notlike 'C:\temp\foldertokeep*' } |
    Sort-Object length -Descending 
) 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接