windows PowerShell:查找并删除其中或子文件夹中没有文件的文件夹
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7034466/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
PowerShell: Find and delete folders that have no files in them or in child folders
提问by Wesley
I have a PowerShell 2.0 script that I use to delete folders that have no files in them:
我有一个 PowerShell 2.0 脚本,用于删除其中没有文件的文件夹:
dir 'P:\path\to\wherever' -recurse | Where-Object { $_.PSIsContainer } | Where-Object { $_.GetFiles().Count -eq 0 } | foreach-object { remove-item $_.fullname -recurse}
However, I noticed that there were a ton of errors when running the script. Namely:
但是,我注意到运行脚本时出现了大量错误。即:
Remove-Item : Directory P:\path\to\wherever cannot be removed because it is not empty.
"WHAT?!"I panicked. They should allbe empty! I filter for only empty folders! Apparently that's not quite how the script is working. In this scenario a folder that has only folders as children, but files as grandchildren is considered empty of files:
“什么?!” 我惊慌失措。他们应该都是空的!我只过滤空文件夹!显然,这不是脚本的工作方式。在这种情况下,只有文件夹作为子文件夹,但作为孙文件的文件夹被认为是空的文件:
Folder1 (no files - 1 folder) \ Folder 2 (one file)
In that case, PowerShell sees Folder1 as being empty and tries to delete it. The reason this puzzles me is because if I right-click on Folder1 in Windows Explorer It says that Folder1 has 1 folder and 1 file within it. Whatever is used to calculate the child objects underneath Folder1 from within Explorer allows it to see grandchild objects ad infinitum.
在这种情况下,PowerShell 将 Folder1 视为空,并尝试将其删除。这让我感到困惑的原因是,如果我在 Windows 资源管理器中右键单击 Folder1,它说 Folder1 中有 1 个文件夹和 1 个文件。无论用于从资源管理器中计算 Folder1 下的子对象,它都可以无限地查看孙对象。
Question:
题:
How can I make my script not consider a folder empty if it has files as grandchildren or beyond?
如果我的脚本将文件作为孙子文件或其他文件,如何让我的脚本不将文件夹视为空?
采纳答案by Wesley
There were some issues in making this script, one of them being using this to check if a folder is empty:
制作此脚本时存在一些问题,其中之一是使用它来检查文件夹是否为空:
{!$_.PSIsContainer}).Length -eq 0
However, I discovered that empty folders are not sized with 0 but rather NULL. The following is the PowerShell script that I will be using. It is notmy own. Rather, it is from PowerShell MVP Richard Siddaway. You can see the thread that this function comes from over at this thread on PowerShell.com.
但是,我发现空文件夹的大小不是 0,而是 NULL。以下是我将使用的 PowerShell 脚本。它不是我自己的。相反,它来自 PowerShell MVP Richard Siddaway。您可以在 PowerShell.com上的此线程中查看该函数来自的线程。
function remove-emptyfolder {
param ($folder)
foreach ($subfolder in $folder.SubFolders){
$notempty = $false
if (($subfolder.Files | Measure-Object).Count -gt 0){$notempty = $true}
if (($subFolders.SubFolders | Measure-Object).Count -gt 0){$notempty = $true}
if ($subfolder.Size -eq 0 -and !$notempty){
Remove-Item -Path $($subfolder.Path) -Force -WhatIf
}
else {
remove-emptyfolder $subfolder
}
}
}
$path = "c:\test"
$fso = New-Object -ComObject "Scripting.FileSystemObject"
$folder = $fso.GetFolder($path)
remove-emptyfolder $folder
回答by manojlds
Updating for recursive deletion:
更新递归删除:
You can use a nested pipeline like below:
您可以使用如下嵌套的管道:
dir -recurse | Where {$_.PSIsContainer -and `
@(dir -Lit $_.Fullname -r | Where {!$_.PSIsContainer}).Length -eq 0} |
Remove-Item -recurse -whatif
(from here - How to delete empty subfolders with PowerShell?)
(从这里开始 -如何使用 PowerShell 删除空子文件夹?)
Add a ($_.GetDirectories().Count -eq 0)
condition too:
也添加一个($_.GetDirectories().Count -eq 0)
条件:
dir path -recurse | Where-Object { $_.PSIsContainer } | Where-Object { ($_.GetFiles().Count -eq 0) -and ($_.GetDirectories().Count -eq 0) } | Remove-Item
Here is a more succinct way of doing this though:
不过,这是一种更简洁的方法:
dir path -recurse | where {!@(dir -force $_.fullname)} | rm -whatif
Note that you do not need the Foreach-Object
while doing remove item. Also add a -whatif
to the Remove-Item
to see if it is going to do what you expect it to.
请注意,您不需要Foreach-Object
while 删除项目。还要在 中添加一个-whatif
以Remove-Item
查看它是否会按照您的预期执行。
回答by Dave Cluderay
Here's a recursive function I used in a recent script...
这是我在最近的脚本中使用的递归函数......
function DeleteEmptyDirectories {
param([string] $root)
[System.IO.Directory]::GetDirectories("$root") |
% {
DeleteEmptyDirectories "$_";
if ([System.IO.Directory]::GetFileSystemEntries("$_").Length -eq 0) {
Write-Output "Removing $_";
Remove-Item -Force "$_";
}
};
}
DeleteEmptyDirectories "P:\Path\to\wherever";
回答by JNK
You can use a recursive function for this. I actually have already written one:
您可以为此使用递归函数。其实我已经写过一篇了:
cls
$dir = "C:\MyFolder"
Function RecurseDelete()
{
param (
[string]$MyDir
)
IF (!(Get-ChildItem -Recurse $mydir | Where-Object {$_.length -ne $null}))
{
Write-Host "Deleting $mydir"
Remove-Item -Recurse $mydir
}
ELSEIF (Get-ChildItem $mydir | Where-Object {$_.length -eq $null})
{
ForEach ($sub in (Get-ChildItem $mydir | Where-Object {$_.length -eq $null}))
{
Write-Host "Checking $($sub.fullname)"
RecurseDelete $sub.fullname
}
}
ELSE
{
IF (!(Get-ChildItem $mydir))
{
Write-Host "Deleting $mydir"
Remove-Item $mydir
}
}
}
IF (Test-Path $dir) {RecurseDelete $dir}