PowerShell自定义函数传Exclude参数后目录名显示不全问题
核心问题原因
这个问题和-Exclude参数的匹配逻辑、传入的排除值都没有关系,本质是PowerShell管道自动展开机制引发的变量类型退化:
- 不指定
-Exclude参数时,Get-ChildItem会返回多个用户目录的信息,经过Select-Object -ExpandProperty Name提取目录名后,$UNC是标准字符串数组,数组索引取到的是完整的目录名称,for循环的逻辑可以正常运行。 - 传入
-Exclude Abraham后,过滤结果仅剩下Public这1个目录项,管道会自动把多元素的集合展开为单个对象输出,此时接收方$UNC拿到的不是数组,而是单个字符串"Public":- PowerShell为了统一接口,会给所有标量对象附加
Count属性,单个字符串的Count值固定为1,因此for循环的执行条件$i -lt $UNC.Count只会触发i=0这一次循环。 - 当对字符串对象执行索引取值(
$UNC[$i])时,PowerShell会把字符串按照字符序列处理,$UNC[0]返回的是字符串的第一个字符"P",而不是完整的目录名——这就是你看到输出0: P的直接原因。
- PowerShell为了统一接口,会给所有标量对象附加
你可以在给
$UNC赋值后加一行调试代码验证:Write-Host $UNC.GetType().FullName,异常场景下会输出System.String,正常无排除的场景下会输出System.Object[]。
修复方案
在给$UNC赋值时,用PowerShell的强制数组包装语法@(),不管管道返回0个、1个还是多个对象,都强制把结果转换为数组类型,从根源上避免标量退化的问题:
# 原有代码 $UNC = Get-ChildItem -Path \\$ComputerName\c$\Users -Exclude $Exclude -Directory | Select-Object -ExpandProperty Name | Sort-Object -Descending # 修改后的代码 $UNC = @(Get-ChildItem -Path \\$ComputerName\c$\Users -Exclude $Exclude -Directory | Select-Object -ExpandProperty Name | Sort-Object -Descending)
修改完成后,哪怕过滤结果只剩1个目录,$UNC也是单元素数组,$UNC[0]取到的就是完整的目录名"Public",for循环的输出就会符合预期。
补充说明
你在控制台直接执行Get-ChildItem -Path C:\users -Exclude "Abraham" -Directory时没有异常,是因为控制台会直接把命令返回的对象渲染输出,没有经过变量赋值、类型转换的环节,因此不会触发管道展开带来的退化问题。
内容的提问来源于stack exchange,提问作者Abraham Zinala
相关产品推荐
相关产品推荐

