[玩转系统] 回归基础:PowerShell Foreach 循环
作者:精品下载站 日期:2024-12-14 20:53:36 浏览:13 分类:玩电脑
回归基础:PowerShell Foreach 循环
当您第一次开始编写 PowerShell 脚本时,您将不可避免地遇到需要处理集合中的多个项目的情况。然后您将需要深入研究 PowerShell foreach 循环并了解它们的全部内容。
几乎所有的编程语言都有一个称为循环的结构。 PowerShell 也不例外。 PowerShell 中最流行的循环类型之一是 foreach 循环。最基本的是,foreach 循环读取整个项目集合,foreach 项目运行某种代码。
对于初学者来说,PowerShell foreach 循环最令人困惑的方面之一是您拥有的所有选项。处理集合中的每一项的方法不只有一种;有三种!
在本文中,您将了解每种类型的 foreach 循环的工作原理以及何时使用其中一种循环。当您读完本文时,您将对每种类型的 foreach 循环有很好的了解。
PowerShell ForEach 循环基础知识
在 PowerShell 中最常见的循环类型之一是 foreach
类型的循环。 foreach
循环读取一组对象(迭代),并在完成最后一个对象后完成。读取的对象集合通常由数组或哈希表表示。
注意:术语“迭代”是一个编程术语,指的是循环的每次运行。每次循环完成一个循环,这称为一次迭代。在一组对象上运行循环的行为通常称为迭代该组。
也许您需要在分布在文件系统中的一些文件夹中创建一个文本文件。假设文件夹路径为 C:\Folder
、C:\Program Files\Folder2
和 C:\Folder3
。如果没有循环,我们就必须引用 Add-Content
cmdlet 三次。
Add-Content -Path 'C:\Folder\textfile.txt' -Value 'This is the content of the file'
Add-Content -Path 'C:\Program Files\Folder2\textfile.txt' -Value 'This is the content of the file'
Add-Content -Path 'C:\Folder2\textfile.txt' -Value 'This is the content of the file'
这些命令参考之间的唯一区别是什么?它是Path
值。 Path
的值是其中每个值中唯一发生变化的值。
你复制了很多代码。你浪费时间打字,并为以后的问题敞开心扉。相反,您应该创建一个仅包含所有正在更改的项目的“集”。对于这个例子,我们将使用一个数组。
$folders = @('C:\Folder','C:\Program Files\Folder2','C:\Folder3')
现在,您已将每个路径存储在单个“集”或数组中。您现在准备好使用循环来迭代这些元素中的每一个。不过,在执行此操作之前,最好先提一下通常会让 PowerShell 新手困惑的主题。与其他类型的循环不同,foreach
循环不同。
从技术上讲,PowerShell 中存在三种类型的 foreach
循环。尽管每种方法的用途都很相似,但理解其中的差异很重要。
foreach 语句
第一种类型的 foreach
循环是一个语句。 foreach
是一个内部 PowerShell 关键字,它既不是 cmdlet,也不是函数。 foreach
语句始终以以下形式使用:foreach ($i in $array)
。
使用上面的示例,$i
变量表示迭代器或 $path
中每个项目的值,因为它迭代 数组中的每个元素。
请注意,迭代器变量不必是 $i
。变量名称可以是任何内容。
在下面的示例中,您可以通过执行以下操作来完成与重复 Add-Content
引用相同的任务:
# Create an array of folders
$folders = @('C:\Folder','C:\Program Files\Folder2','C:\Folder3')
# Perform iteration to create the same file in each folder
foreach ($i in $folders) {
Add-Content -Path "$i\SampleFile.txt" -Value "This is the content of the file"
}
众所周知,foreach
语句比使用 ForEach-Object
cmdlet 更快。
ForEach-Object CmdLet
如果 foreach
是一个语句并且只能以单一方式使用,那么 ForEach-Object
是一个带有参数的 cmdlet,可以以多种不同的方式使用。与foreach
语句类似,ForEach-Object
cmdlet 可以迭代一组对象。只是这一次,它传递了该组对象以及对每个对象采取的操作作为参数,如下所示。
$folders = @('C:\Folder','C:\Program Files\Folder2','C:\Folder3')
$folders | ForEach-Object (Add-Content -Path "$_\SampleFile.txt" -Value "This is the content of the file")
注意:为了让事情变得混乱,ForEach-Object
cmdlet 有一个名为 foreach
的别名。根据术语“foreach”的调用方式,运行 foreach
语句,或运行 ForEach-Object
。
区分这些情况的一个好方法是注意术语“foreach”后面是否跟着 ($someVariable in $someSet)
。否则,在任何其他上下文中,代码作者可能会使用 ForEach-Object
的别名。
foreach()
方法
PowerShell v4 中引入了最新的 foreach
循环之一,称为 foreach()
方法。此方法存在于数组或集合对象上。 foreach()
方法有一个标准脚本块参数,其中包含接管每次迭代的操作,就像其他迭代一样。
$folders = @('C:\Folder','C:\Program Files\Folder2','C:\Folder3')
$folders.ForEach({
Add-Content -Path "$_\SampleFile.txt" -Value "This is the content of the file"
})
foreach() 方法最显着的区别在于它在底层的工作方式。
使用 foreach()
方法要快得多,并且在大型集合上尤其如此。如果可能的话,建议使用此方法而不是其他两种方法。
迷你项目:循环一组服务器名称
PowerShell 中循环最常见的用途之一是从某个源读取一组服务器并对每个服务器执行某些操作。对于我们的第一个小型项目,让我们构建一些代码,允许我们从文本文件中读取服务器名称(每行一个)并 ping 每台服务器以确定它们是否在线。
对于此工作流程,您认为哪种类型的循环效果最好?
请注意,我在“服务器集”中提到了“集”一词。这是一条线索。您已经拥有指定数量的服务器名称,并且您希望对其中的每个执行一些操作。这听起来是一个尝试最常用的 PowerShell 循环的好机会; foreach
循环。
第一个任务是在代码中创建一组服务器名称。最常见的方法是创建一个数组。对我们来说幸运的是,默认情况下,Get-Content
返回一个数组,数组中的每个元素都由文本文件中的一行表示。
首先,创建一个包含所有服务器名称的数组,并将其命名为 $servers
。
$servers = Get-Content .\servers.txt
现在您已经创建了阵列,您现在需要确认每个服务器是否在线。用于测试服务器连接的一个很棒的 cmdlet 称为 Test-Connection
。此 cmdlet 在计算机上执行一些连接测试,以查看其是否在线。
通过在 foreach
循环内执行 Test-Connection
来读取每个文件行,您可以将 $server
变量表示的每个服务器名称传递给测试连接
。这就是 PowerShell 循环遍历文本文件的方式。您可以在下面查看其工作原理的示例。
foreach ($server in $servers) {
try {
$null = Test-Connection -ComputerName $server -Count 1 -ErrorAction STOP
Write-Output "$server - OK"
}
catch {
Write-Output "$server - $($_.Exception.Message)"
}
}
当执行 foreach
循环时,它将如下所示:
您现在已经成功测试了充满服务器名称的文本文件的连接!此时,您现在可以在文本文件中随意添加或删除服务器名称,而无需更改代码。
您已经成功实践了我们一直宣扬的 DRY 方法。
ForEach PowerShell 示例
让我们看几个如何使用 ForEach 循环的示例。这些基于现实世界的用例,显示了您可以修改以满足您的要求的概念。
示例 1:使用 ForEach 语句在目录中的每个子文件夹中创建文件
此示例演示了 PowerShell foreach 目录中文件夹的常见用法。
假设 C:\ARCHIVE_VOLUMES
文件夹中有十个子文件夹。每个子文件夹代表一个每天备份的存档卷。每次备份完成后,都会在每个文件夹内创建一个名为 BackupState.txt
的文件,其中包含备份日期。
您可以在下面看到一个示例。
下面的脚本执行三个操作:
- 获取
C:\ARCHIVE_VOLUMES
内所有子文件夹的列表 - 循环遍历每个文件夹
- 创建一个名为
BackupState.txt
的文本文件,其中包含当前日期和时间及其值
下面的示例使用 foreach
语句。
# Define the TOP-level folder
$TOP_FOLDER = "C:\ARCHIVE_VOLUMES"
# Get all sub folders recursively
$Child_Folders = Get-ChildItem -Path $TOP_FOLDER -Recurse | Where-Object { $_.PSIsContainer -eq $true }
# Create a text file in each sub-folder and add the current date/time as value.
foreach ($foldername in $Child_Folders.FullName) {
(get-date -Format G) | Out-File -FilePath "$($foldername)\BackupState.txt" -Force
}
使用 Get-ChildItem
cmdlet,您可以确认每个子文件夹内的文件已创建或更新。
Get-ChildItem -Recurse -Path C:\ARCHIVE_VOLUMES -Include backupstate.txt | Select-Object Fullname,CreationTime,LastWriteTime,Length
下面的屏幕截图显示了脚本的输出,其中显示了每个子目录中找到的所有 BackupState.txt
文件。
示例2:读取子目录中每个文本文件的内容
接下来,为了演示如何使用 PowerShell foreach 目录中的文件,下面的脚本将读取示例 1 中创建的每个 BackupState.txt
文件。
- 递归查找每个子目录中的所有
BackupState.txt
文件。 - 使用
foreach
语句读取每个文本文件以获取“上次备份时间”值。 - 在屏幕上显示结果。
## Find all BackupState.txt files in C:\ARCHIVE_VOLUMES
$files = Get-ChildItem -Recurse -Path C:\ARCHIVE_VOLUMES -Include 'BackupState.txt' | Select-Object DirectoryName,FullName
## Read the contents of each file
foreach ($file in $files) {
Write-Output ("$($file.DirectoryName) last backup time - " + (Get-Content $file.FullName))
}
在 PowerShell 会话中执行脚本后,您应该会看到与下面的屏幕截图类似的输出。这表明 PowerShell 循环文件、读取内容并显示输出。
示例 3:使用 ForEach-Object CmdLet 获取服务并启动它们
系统管理员通常需要获取服务的状态并触发手动或自动工作流程来修复任何失败的服务。让我们看一下使用 ForEach-Object
cmdlet 的示例脚本。
对于本示例,下面的脚本将执行以下操作:
- 获取配置为自动启动但当前未处于运行状态的服务的列表。
- 接下来,列表中的项目通过管道传输到
ForEach-Object
cmdlet 以尝试启动每个服务。 - 根据
Start-Service
命令的结果,显示成功或失败消息。
## Get a list of automatic services that are stopped.
$services = Get-Service | Where-Object {$.StartType -eq 'Automatic' -and $.Status -ne 'Running'}
## Pass each service object to the pipeline and process them with the Foreach-Object cmdlet
$services | ForEach-Object {
try {
Write-Host "Attempting to start '$($.DisplayName)'"
Start-Service -Name $.Name -ErrorAction STOP
Write-Host "SUCCESS: '$($.DisplayName)' has been started"
} catch {
Write-output "FAILED: $($.exception.message)"
}
}
执行脚本时,它将类似于下面的输出屏幕截图。如您所见,每个服务都发出了启动命令。有的启动成功,有的启动失败。
示例 4:使用 ForEach()
方法从 CSV 读取数据
使用 CSV 文件中的数据在系统管理员中很流行。使用 Import-CSV
和 ForEach
组合将记录放入 CSV 文件中可以轻松运行批量操作。此组合通常用于在 Active Directory 中创建多个用户。
在下一个示例中,假设您有一个包含两列的 CSV 文件 - 名字和姓氏。然后应使用新用户的姓名填充该 CSV 文件,以便被创建。 CSV 文件如下所示。
"Firstname","Lastname"
"Grimm","Reaper"
"Hell","Boy"
"Rick","Rude"
现在进入下一个脚本块。首先,通过将内容路径传递给 Import-CSV
cmdlet 来导入 CSV 文件。然后,使用 foreach()
方法循环访问名称并在 Active Directory 中创建新用户。
# Import list of Firstname and Lastname from CSV file
$newUsers = Import-Csv -Path .\Employees.csv
Add-Type -AssemblyName System.Web
# Process the list
$newUsers.foreach(
{
# Generate a random password
$password = [System.Web.Security.Membership]::GeneratePassword((Get-Random -Minimum 20 -Maximum 32), 3)
$secPw = ConvertTo-SecureString -String $password -AsPlainText -Force
# Formulate a username
$userName = '{0}{1}' -f $_.FirstName.Substring(0, 1), $_.LastName
# Build new user attributes
$NewUserParameters = @{
GivenName = $_.FirstName
Surname = $_.LastName
Name = $userName
AccountPassword = $secPw
}
try {
New-AdUser @NewUserParameters -ErrorAction Stop
Write-Output "User '$($userName)' has been created."
}
catch {
Write-Output $_.Exception.Message
}
}
)
运行时,您现在应该已经为 CSV 文件中的每一行创建了一个 AD 用户!
概括
PowerShell 中 foreach 循环背后的逻辑与其他编程语言没有什么不同。它仅随着其使用方式以及为任何特定任务选择 foreach 循环的哪种变体而变化。
在本文中,您了解了 PowerShell 中可用的不同类型的 foreach 循环,以及在使用哪种循环时应考虑的因素。您还了解了使用不同示例场景的三种类型的 foreach 循环。
进一步阅读
- 使用 Import-Csv(foreach 循环)在 PowerShell 中管理 CSV 文件
- New-ADUser:使用 PowerShell 创建 Active Directory 用户
- PowerShell 循环基础知识:Foreach |脚本博客
猜你还喜欢
- 03-30 [玩转系统] 如何用批处理实现关机,注销,重启和锁定计算机
- 02-14 [系统故障] Win10下报错:该文件没有与之关联的应用来执行该操作
- 01-07 [系统问题] Win10--解决锁屏后会断网的问题
- 01-02 [系统技巧] Windows系统如何关闭防火墙保姆式教程,超详细
- 12-15 [玩转系统] 如何在 Windows 10 和 11 上允许多个 RDP 会话
- 12-15 [玩转系统] 查找 Exchange/Microsoft 365 中不活动(未使用)的通讯组列表
- 12-15 [玩转系统] 如何在 Windows 上安装远程服务器管理工具 (RSAT)
- 12-15 [玩转系统] 如何在 Windows 上重置组策略设置
- 12-15 [玩转系统] 如何获取计算机上的本地管理员列表?
- 12-15 [玩转系统] 在 Visual Studio Code 中连接到 MS SQL Server 数据库
- 12-15 [玩转系统] 如何降级 Windows Server 版本或许可证
- 12-15 [玩转系统] 如何允许非管理员用户在 Windows 中启动/停止服务
取消回复欢迎 你 发表评论:
- 精品推荐!
-
- 最新文章
- 热门文章
- 热评文章
[影视] 黑道中人 Alto Knights(2025)剧情 犯罪 历史 电影
[古装剧] [七侠五义][全75集][WEB-MP4/76G][国语无字][1080P][焦恩俊经典]
[实用软件] 虚拟手机号 电话 验证码 注册
[电视剧] 安眠书店/你 第五季 You Season 5 (2025) 【全10集】
[电视剧] 棋士(2025) 4K 1080P【全22集】悬疑 犯罪 王宝强 陈明昊
[软件合集] 25年6月5日 精选软件22个
[软件合集] 25年6月4日 精选软件36个
[短剧] 2025年06月04日 精选+付费短剧推荐33部
[短剧] 2025年06月03日 精选+付费短剧推荐25部
[软件合集] 25年6月3日 精选软件44个
[剧集] [央视][笑傲江湖][2001][DVD-RMVB][高清][40集全]李亚鹏、许晴、苗乙乙
[电视剧] 欢乐颂.5部全 (2016-2024)
[电视剧] [突围] [45集全] [WEB-MP4/每集1.5GB] [国语/内嵌中文字幕] [4K-2160P] [无水印]
[影视] 【稀有资源】香港老片 艺坛照妖镜之96应召名册 (1996)
[剧集] 神经风云(2023)(完结).4K
[剧集] [BT] [TVB] [黑夜彩虹(2003)] [全21集] [粤语中字] [TV-RMVB]
[实用软件] 虚拟手机号 电话 验证码 注册
[资源] B站充电视频合集,包含多位重量级up主,全是大佬真金白银买来的~【99GB】
[影视] 内地绝版高清录像带 [mpg]
[书籍] 古今奇书禁书三教九流资料大合集 猎奇必备珍藏资源PDF版 1.14G
[电视剧] [突围] [45集全] [WEB-MP4/每集1.5GB] [国语/内嵌中文字幕] [4K-2160P] [无水印]
[剧集] [央视][笑傲江湖][2001][DVD-RMVB][高清][40集全]李亚鹏、许晴、苗乙乙
[电影] 美国队长4 4K原盘REMUX 杜比视界 内封简繁英双语字幕 49G
[电影] 死神来了(1-6)大合集!
[软件合集] 25年05月13日 精选软件16个
[精品软件] 25年05月15日 精选软件18个
[绝版资源] 南与北 第1-2季 合集 North and South (1985) /美国/豆瓣: 8.8[1080P][中文字幕]
[软件] 25年05月14日 精选软件57个
[短剧] 2025年05月14日 精选+付费短剧推荐39部
[短剧] 2025年05月15日 精选+付费短剧推荐36部
- 最新评论
-
- 热门tag