我对Powershell相当陌生。我试图通过引用作为备份一部分创建的每个GPO备份的“ gpresult.xml”文件中的名称来重写GPO备份文件夹的名称,以使用其友好名称而不是其GUID。但是,我不明白如何引用正在读入ForEach-Object循环中的特定对象(在这种情况下为文件夹名称),以便读入此文件夹下的文件。
function Backup_GPO {
$stamp = Get-Date -UFormat "%m%d"
New-Item -ItemType "directory" -Name $stamp -Path \\dc-16\share\GPO_Backups -Force | out-null # create new folder to specify day backup is made
Backup-GPO -All -Path ("\\dc-16\share\GPO_Backups\" + "$stamp\" )
Get-ChildItem -Path \\dc-16\share\GPO_Backups\$stamp | ForEach-Object {
# I want to reference the current folder here
[xml]$file = Get-Content -Path (folder that is being referenced in for loop)\gpresult.xml
$name = $file.GPO.Name
}
我来自Python,如果我想引用当前正在迭代的对象,则可以非常简单地进行操作-
for object in list:
print(object)
如何在Powershell的ForEach-Object命令中引用当前正在使用的对象?
答案 0 :(得分:3)
我来自Python,如果我想引用我当前所在的对象 反复进行,我可以非常简单地做到这一点-
for object in list: print(object)
PowerShell中的直接等效项是 foreach
声明(循环):
$list = 1..3 # create a 3-element array with elements 1, 2, 3
foreach ($object in $list) {
$object # expression output is *implicitly* output
}
请注意,您不能在PowerShell 管道 中直接使用foreach
声明。
在管道中,必须改为使用ForEach-Object
cmdlet ,这可能会引起混淆-在某些情况下可能会引用 与foreach
一样,通过alias-仅parsing mode才可以区分语句和cmdlet的别名。
您正在管道 中使用ForEach-Object
cmdlet ,其中适用不同的规则
传递到管道处理 cmdlet 的脚本块({{ ... }
)(例如ForEach-Object
和Where-Object
确实没有显式的符号。 foreach
语句提供的迭代变量。
相反,按照惯例,此类脚本块将当前管道输入对象视为automatic variable $_
-或更冗长的是$PSItem
。
虽然 foreach
语句和ForEach-Object
cmdlet 在一定的抽象级别上运行相同,但是存在根本区别:>
foreach
声明对内存中预先收集的完整集合进行操作。
ForEach-Object
cmdlet 对流输入进行操作,逐个对象,因为每个对象都是通过管道接收的。
此差异等于以下权衡:
使用foreach
语句以获得更好的性能,但以牺牲内存使用为代价。
将ForEach-Object
cmdlet 用于恒定内存使用,并且还可能用于单个管道的句法优雅 ,而牺牲了 performance 的性能-但是,对于非常大的输入集,这可能是唯一的选择(假设您还没有在输出)。
答案 1 :(得分:2)
在ForEach-Object
脚本块内,将要迭代的当前项目复制到$_
:
Get-ChildItem -Filter gpresult.xml |ForEach-Object {
# `$_` is a FileInfo object, `$_.FullName` holds the absolute file system path
[xml]$file = Get-Content -LiteralPath $_.FullName
}
如果要指定自定义名称,则可以指定-PipelineVariable
名称:
Get-ChildItem -Filter gpresult.xml -PipelineVariable fileinfo |ForEach-Object {
# `$fileinfo` is now a FileInfo object, `$fileinfo.FullName` holds the absolute file system path
[xml]$file = Get-Content -LiteralPath $fileinfo.FullName
}
或使用foreach
循环语句,就像python中的for object in list
:
foreach($object in Get-ChildItem -Filter gpresult.xml)
{
[xml]$file = Get-Content -LiteralPath $object.FullName
}
答案 2 :(得分:0)
另一种方式...
$dlist = Get-ChildItem -Path "\\dc-16\share\GPO_Backups\$stamp"
foreach ($dir in $dlist) {
# I want to reference the current folder here
[xml]$file = Get-Content -Path (Join-Path -Path $_.FullName -ChildPath 'gpresult.xml')
$name = $file.GPO.Name
}
答案 3 :(得分:0)
这是我的解决方案。令人讨厌的是$ _没有完整的路径。 $ gpath比$ _。fullname更容易使用,因为在下一行使用get-content将两个字符串连接在一起。尝试backup-gpo时,我得到一个gpreport.xml文件。显然,不能将。\ gpo_backups \等相对路径与backup-gpo一起使用。
mkdir c:\users\js\gpo_backups\
get-gpo -all | where displayname -like '*mygpo*' |
backup-gpo -path c:\users\js\gpo_backups\
Get-ChildItem -Path .\GPO_Backups\ | ForEach-Object {
$gpath = $_.fullname
[xml]$file = Get-Content -Path "$gpath\gpreport.xml"
$file.GPO.Name
}