我有一些代码旨在为不在驱动器号列表中的每个磁盘驱动器返回PSDriveInfo对象。我可以求逆,也可以对它进行编码,但是我真的很想了解我要去哪里。我的服务器有7个硬盘驱动器(C,D,E,H,I,L,W),我的代码旨在为除驱动器E和H之外的所有驱动器返回PSDriveInfo对象。
我尝试了各种比较运算符-ne
,.ToString().Trim().Equals()
和-match
。我的代码当前基于RegEx -match
运算符。如果我使用-match
,我得到的就是我想要的东西,但是如果我使用-notmatch
,我得到了每个驱动器,我感到困惑,为什么这不起作用。在代码窗口中,我首先显示有效的方法,然后给出与我想要的相反的代码,然后使使用-notmatch
运算符的代码使我感到困惑。
Clear-Host
$exclude = "E,H"
"This gives me the inverse of what I want:"
Get-WmiObject Win32_LogicalDisk | Where-Object {
$_.DriveType -eq 3
} | ForEach-Object {
Get-PSDrive $_.DeviceId[0]
} | Where-Object {
$driveName = $_.Name
$exclude -split "," | ForEach-Object {
if ($driveName -match $_) { return $true }
}
} | ForEach-Object {
$_.Name
}
"Why does this not work:"
Get-WmiObject Win32_LogicalDisk | Where-Object {
$_.DriveType -eq 3
} | ForEach-Object {
Get-PSDrive $_.DeviceId[0]
} | Where-Object {
$driveName = $_.Name
$exclude -split "," | ForEach-Object {
if ($driveName -notmatch $_) { return $true }
}
} | ForEach-Object {
$_.Name
}
服务器上的代码示例的结果:
这与我使用-match
的含义相反:
E H
为什么-notmatch
不起作用?
C D E H I L W
答案 0 :(得分:3)
在您的-notmatch
尝试中,您正在检查最后Where-Object
内排除类别中的每个项目与类型3的每个驱动器。因此,您将始终获得至少一个$true
评估。因此,这意味着where-object
条件将始终等于$true
。
这是一个琐碎的事,尽管仍然很令人费解,它是正在发生的事的例子:
# Example 1
@(1,2,3,4) | where-object { $num = $_; $true,$false,$true |% {if ($_) {$num}}}
1
2
3
4
#Example 2:
@(1,2,3,4) | where-object { $num = $_; $false,$false,$false |% {if ($_) {$num}}}
上面的示例1总是最终求值为$true
,以允许输出当前数组对象。示例2从不将$true
传递到if
语句中,因此它什么也不返回。您的-notmatch
代码起作用的唯一方法是,如果没有匹配项,说实话,我不知道何时会发生。
我已采用您的代码并对其进行了修改,以向您显示正在发生的事情。如果运行此命令,则将看到每个驱动器至少返回一个True
。
$exclude = "E,H"
Get-wmiobject Win32_LogicalDisk |
Where-Object {
$_.drivetype -eq 3
} |
ForEach-Object {
Get-PSDrive $_.deviceid[0]
} |
foreach-Object {
$driveName = $_.Name
$exclude -split "," |
ForEach-Object{
"Testing Drive $driveName -notmatch $_"
if( $driveName -notmatch $_ ){ $true }
else {$false}
}
}
使用上述代码进行测试:
Testing Drive H -notmatch E
True
Testing Drive H -notmatch H
False
Testing Drive O -notmatch E
True
Testing Drive O -notmatch H
True
Testing Drive T -notmatch E
True
Testing Drive T -notmatch H
True
解决此问题的一种更简单的方法是使用-notin
运算符。
$exclude = "E:","H:"
Get-WmiObject Win32_LogicalDisk |
Where-Object {$_.DriveType -eq 3 -and $_.DeviceId -notin $exclude}
在上面的代码中,$exclude
已经是一个数组,每个值都包含:
,以简化代码。如果您不想在变量中包含:
,则可以在下一行中将其连接起来,如下所示:
$exclude = "E","H" | Foreach-Object {"{0}:" -f $_}
Get-WmiObject Win32_LogicalDisk |
Where-Object {$_.DriveType -eq 3 -and $_.DeviceId -notin $exclude}
答案 1 :(得分:2)
您的逻辑...令人费解,脆弱,无法正确说明push
和-match
对集合的工作方式。一种更合乎逻辑的方法是使用-notmatch
或-in
集合运算符。
-notin
输出...
$ComputerName = $env:COMPUTERNAME
$ExcludedDriveList = 'e', 'h'
$DriveLetterList = @(Get-CimInstance -ClassName CIM_LogicalDisk |
Where-Object {
$_.DriveType -eq 3 -and
$_.DeviceID.Trim(':') -notin $ExcludedDriveList
}
).DeviceID.Trim(':')
$DriveLetterList
那只是HD / SSD项,我有两个dvd-r驱动器和一个未列出的读卡器。 [咧嘴]
答案 2 :(得分:1)
问题在于"E", "H" -NotMatch "E"
将返回“ H”-请参见Microsoft Docs on Comparison Operators。在这种情况下,您想要的只是取消您的if
语句:
...
if(!( $driveName -match $_ )) { return $true } # or if (-not ($driveName -match $_ ))
...