例如:_archive
,_DO_NOT_DELETE
,_processing
等
我使用了下面的代码,但它不起作用。看来exclude不能与递归一起使用。有什么想法吗?
$exclude = @("_*")
$source = "C:\code\Powershell\delete empty folders\New folder\"
$allitems = Get-ChildItem $source -Directory -Exclude $exclude -Recurse
foreach($myItem in $allitems)
{
echo $myItem.fullname
}
输出:
C:\code\Powershell\delete empty folders\New folder\New folder\New folder C:\code\Powershell\delete empty folders\New folder\New folder\New folder\New folder C:\code\Powershell\delete empty folders\New folder\New folder\New folder (2) C:\code\Powershell\delete empty folders\New folder\New folder\New folder (3) C:\code\Powershell\delete empty folders\New folder\New folder\New folder (3)\New folder C:\code\Powershell\delete empty folders\New folder\_archive\New folder
因此,正如我之前告诉我的那样,我要避免使用下划线开头的目录,因此最后一行不应该出现。
即使我也使用下面的代码,输出仍然相同:
$exclude = @("_*")
$source = "C:\code\Powershell\delete empty folders\New folder\"
$allitems = Get-ChildItem $source -Recurse -Directory |
Where {$_.FullName -notlike $exclude}
foreach($myItem in $allitems)
{
echo $myItem.fullname
}
答案 0 :(得分:4)
这里发生的是,Get-ChildItem的-exclude
参数基于项目的name属性工作。使用通配符时,名称必须与非通配符部分匹配。当目录名以空格开头时,不会发生这种情况。我们来看一个例子:
# Create two files, one starts with a space, the other doesn't
Set-Content -Path " data1.txt" -Value $null
Set-Content -Path "data2.txt" -Value $null
gci -name "data*"
data2.txt
gci -name " data*"
data1.txt
结果是一场比赛,使用了通配符。原因是data1.txt
的第一个字符是空格,并且与参数的第一个字符d
不匹配。
-exclude
因棘手而臭名昭著。通过将结果传递到where-object
,通常更容易解决。像这样
Get-ChildItem $source -Directory -recurse | ? {$_.fullname -NotMatch "\\\s*_"} | % { $_.fullname }
# "\\\s*_" is regex for \, any amount of whitespace, _
C:\code\Powershell\delete empty folders\New folder\New folder
C:\code\Powershell\delete empty folders\New folder\New folder\New folder
C:\code\Powershell\delete empty folders\New folder\New folder\New folder (2)
C:\code\Powershell\delete empty folders\New folder\New folder\New folder (3)
C:\code\Powershell\delete empty folders\New folder\New folder\New folder\New folder
C:\code\Powershell\delete empty folders\New folder\New folder\New folder (3)\New folder
Get-ChildItem $source -Directory -recurse | ? {$_.fullname -Match "\\\s*_"} | % { $_.fullname }
C:\code\Powershell\delete empty folders\New folder\ _archive
C:\code\Powershell\delete empty folders\New folder\ _archive\New folder
请注意,匹配需要评估FullName
属性。仅使用Name
只会匹配叶子级别。
答案 1 :(得分:1)
尚未找到第一次尝试的答案。但是,如果要使用Where-Object
,则必须将过滤器从_*
更改为*_*
。
这是因为.Fullname
显示了完整路径,因此在实际路径_
之前还有更多字符。
$exclude = @("*_*")
$source = "C:\code\Powershell\delete empty folders\New folder\"
$allitems = Get-ChildItem $source -Recurse -Directory | Where {$_.FullName -notlike $exclude}
$allitems.Fullname
应该给您期望的输出。
答案 2 :(得分:1)
正如@Paxz在评论中所说,该命令正在按预期方式工作,只是没有您希望的那样。它肯定从输出中排除了以_
开头的文件夹,但这不适用于-Recurse
开关,因此它仍在这些文件夹中查找其他项目,并显示(如果它们的名称确实如此)不是以_
开头。
您可以使用自己的过滤器获取所需内容:
Get-ChildItem -Path $source -Directory -recurse |
Where-Object {$_.FullName -notlike "*\_*"} |
Format-Table FullName
请注意,这仍然会找到所有带有_
的文件夹,但只会丢弃它们(因此,性能没有改善)。另外,使用更简单的过滤器:-notlike "*_*"
会排除名称中部或结尾带有下划线的所有文件夹(例如Hello_World
),而不仅仅是开头。