用于循环和比较的 Powershell 数组方法?

Powershell Array methods for looping and comparison?

我有各种各样的计算机,我正在编写一个 Powershell 脚本,它在我的服务器上安装一个网络共享和计算机驱动程序的本地存储库,这些驱动程序保存在它们自己单独的目录中,作为每台机器的品牌和型号(例如 Lenovo E460、Dell Latitude E5450 等)

这是我正在尝试做的事情:

我想要获取计算机的信息(品牌和型号)并将其连接成一个字符串。然后我希望该字符串被引用到驱动程序目录数组中,如果计算机 make + model 匹配,我希望计算机下载该目录中的驱动程序。我来自网络开发背景,这里是我通常使用 JavaScript Array.prototype.filter() 方法过滤数组以将 $computer 与 [=13] 中的每个子项进行比较的地方=]数组。

$computer = (gwmi Win32_ComputerSystem).Manufacturer + " " + (dwmi Win32_ComputerSystem).Model
$drivers = Get-ChildItem \zapp\pc\!Drivers

Powershell 实现此目的的最佳方法是什么? Powershell有没有类似JavaScript的过滤比较Array的方法?或者 Foreach -match-eq 是最有效的书写方式吗?

谢谢!

大家好,晚上好。

直到有人比我聪明得多(不会很长),我可以尝试为您指明正确的方向。

这里实际上有几个选项。您可以使用依赖布尔值(布尔值 - 只是时髦的说法)的条件语句,并且 Where-Object 与一些运算符相结合。

让我先 post 这样它就不会在我身上崩溃(弄坏了我的屏幕并且它的行为很不稳定)。我们将从 Switch 声明开始。如果满足条件,则执行某些操作。

$computer = (gwmi Win32_ComputerSystem).Manufacturer + " " + (gwmi Win32_ComputerSystem).Model
$drivers = Get-ChildItem \zapp\pc\!Drivers | Select-Object -ExpandProperty Name
    Switch ($drivers){
        "$computer" {"Found: $_" }
        
        }

我回来了! 所以,回到我离开的地方......你可以使用 switch 语句,它会在满足特定条件时执行某些操作;在这种情况下,一旦它检测到字符串与您要查找的内容匹配,它就会从远程 PC 执行一个复制项目到本地 PC。见下文:

$computer = (gwmi Win32_ComputerSystem).Manufacturer + " " + (gwmi Win32_ComputerSystem).Model
    Switch (Get-ChildItem \zapp\pc\!Drivers){
        "$computer" {Copy-Item -Path $_.FullName -Destination C:\DriverStore }
            }

使用 Foreach 循环,我们可以遍历每个文件并尝试使用 if 语句匹配您传递给它的值,在 Copy-Item 上执行找到后将远程 PC 连接到您的电脑上。

Foreach($file in (Get-ChildItem \zapp\pc\!Drivers)){
    if($file -match  $computer){ Copy-Item -Path $file.FullName -Destination C:\DriverStore}
        }

接下来,我们只是在 -match 运算符的帮助下将文件传输到 Where-Object,将指定给它的值与左侧的对象进行匹配。 Foreach-Object cmdlet(不要与 Foreach 混淆)在末尾使用,参数为 -Process 到 运行 输入对象中的每个元素。然后将与您的 PC 匹配的文件夹从远程 PC 复制到您的文件夹。

$computer = (gwmi Win32_ComputerSystem).Manufacturer + " " + (gwmi Win32_ComputerSystem).Model
Get-ChildItem \zapp\pc\!Drivers | Where-Object {$_.Name -match $computer} |ForEach-Object -process{ Copy-Item -Path $_.fullname -Destination C:\DriverStore}

希望这是有道理的,可以让你走上正轨。为了简单起见,我没有提到其他几个方法,但是@Lee_Daily 确实提到了也可以在这种情况下使用的 .Where() 方法。

您应该能够在没有数组或任何(显式)过滤的情况下完成此操作。

首先,为了效率起见,我会像这样初始化 $computer...

$computerSystem = gwmi Win32_ComputerSystem -Property 'Manufacturer', 'Model'
$computer = $ComputerSystem.Manufacturer + " " + $computerSystem.Model

如果你想变漂亮你也可以...

$computer = $computerSystem.Manufacturer, $computerSystem.Model -join " "

现在,您可以让文件系统为您完成这些工作,而不是您自己管理和搜索一系列驱动程序目录...

$driverDirectory = Get-Item -LiteralPath "\zapp\pc\!Drivers$computer"

如果指定路径上不存在对象,这将引发错误。你可以像这样对抗...

$driverDirectory = Get-Item -LiteralPath "\zapp\pc\!Drivers$computer" -ErrorAction SilentlyContinue
if ($null -ne $driverDirectory)
{
    # $driverDirectory exists; copy drivers
}

...或者像这样...

$driverDirectoryPath = "\zapp\pc\!Drivers$computer"
if (Test-Path -Path $driverDirectoryPath)
{
    # $driverDirectoryPath exists; copy drivers
}

这样做的唯一真正缺点是,如果 !Drivers\ 是一个巨大的目录(即数千个子目录)并且您反复查找驱动程序目录,那么该目录枚举可能比自己将结果缓存在数组中要慢得多。我猜你的脚本只会复制适用于本地系统的驱动程序,所以,就像我说的,我会让文件系统做它最擅长的事情。