Arrays 将两个不同的Get ChildItem调用的结果合并到一个变量中,对它们执行相同的处理
我正试图编写一个PowerShell脚本,从几个目录构建一个文件列表。将所有目录添加到主列表后,我希望对所有文件执行相同的处理 这就是我所拥有的:Arrays 将两个不同的Get ChildItem调用的结果合并到一个变量中,对它们执行相同的处理,arrays,powershell,get-childitem,Arrays,Powershell,Get Childitem,我正试图编写一个PowerShell脚本,从几个目录构建一个文件列表。将所有目录添加到主列表后,我希望对所有文件执行相同的处理 这就是我所拥有的: $items = New-Object Collections.Generic.List[IO.FileInfo] $loc1 = @(Get-ChildItem -Path "\\server\C$\Program Files (x86)\Data1\" -Recurse) $loc2 = @(Get-ChildItem -Path "\\ser
$items = New-Object Collections.Generic.List[IO.FileInfo]
$loc1 = @(Get-ChildItem -Path "\\server\C$\Program Files (x86)\Data1\" -Recurse)
$loc2 = @(Get-ChildItem -Path "\\server\C$\Web\DataStorage\" -Recurse)
$items.Add($loc1) # This line fails (the next also fails)
$items.Add($loc2)
# Processing code is here
出现此错误时失败:
无法将参数“0”转换为
值:“System.Object[]”,表示“添加到”
键入“System.IO.FileInfo”:“无法”
转换“System.Object[]”值
类型为“System.Object[]”的
“System.IO.FileInfo”
我最感兴趣的是,对于这种情况,什么是正确的方法。我意识到我的代码是一种非常有效的方法——如果有一种更强大的方法来完成同样的任务,我完全赞成。关键是,
$loc#
的数量可能会随着时间的推移而变化,因此在生成的代码中添加和删除一两个应该很容易。不确定您是否需要一个通用列表。您可以只使用PowerShell阵列,例如:
$items = @(Get-ChildItem '\\server\C$\Program Files (x86)\Data1\' -r)
$items += @(Get-ChildItem '\\server\C$\Web\DataStorage\' -r)
PowerShell阵列可以使用+=
连接,Keith的答案是PowerShell的方式:只需使用@(…)+@(…)。
如果确实需要类型安全列表[IO.FileInfo],则需要使用AddRange,并将对象数组强制转换为FileInfo数组——还需要确保不获取任何DirectoryInfo对象,否则需要使用IO.FileSystemInfo作为列表类型:
因此,避免使用目录:
$items = New-Object Collections.Generic.List[IO.FileInfo]
$items.AddRange( ([IO.FileSystemInfo[]](ls '\\server\C$\Program Files (x86)\Data1\' -r | Where { -not $_.PSIsContainer } )) )
$items.AddRange( ([IO.FileSystemInfo[]](ls '\\server\C$\Web\DataStorage\' -r | Where { -not $_.PSIsContainer } )) )
或者使用FileSystemInfo(FileInfo和DirectoryInfo的公共基类):
下面是一种可能更像PowerShell的方法,它根本不需要部分串联或向结果中显式添加项:
# Collect the results by two or more calls of Get-ChildItem
# and perhaps do some other job (but avoid unwanted output!)
$result = .{
# Output items
Get-ChildItem C:\TEMP\_100715_103408 -Recurse
# Some other job
$x = 1 + 1
# Output some more items
Get-ChildItem C:\TEMP\_100715_110341 -Recurse
#...
}
# Process the result items
$result
但是脚本块中的代码应该编写得更仔细一些,以避免不必要的输出与文件系统项混合在一起
编辑:或者,也许更有效,我们可以代替{…}
使用@(…)
或$(…)
其中..
表示包含多个
从Get-help Get-ChildItem调用
Get-ChildItem
:
-路径
指定一个或多个位置的路径。允许使用通配符。默认位置是当前目录(.)
-Filter
比-Include
性能更好,因此如果没有很多不同的扩展名,只需将两个过滤列表连接起来可能会更快
$files=Get ChildItem-Path“H:\stash\”-Filter*.rdlc-Recurse
$files+=Get ChildItem-Path“H:\stash\”-Filter*.rdl-Recurse
我将输出与计时器进行了比较,如下所示:
$stopwatch=[System.Diagnostics.stopwatch]::StartNew()
#在这里做事
$stopwatch.Stop()
写入主机“$([Math]::Round($stopwatch.appeased.TotalSeconds))秒数”
这是最好、最简洁的方法,我应该补充一点,您现在可以(在PS4+中)使用-file
打开Get ChildItem
(别名ls
)而不是使用| where object{-而不是$\pscontainer}
我实际上是指您的/Keith解决方案@(…)+@(…)(…)
:-)很棒的解决方案!我有一个类似的问题,但我使用JSON对象,并使用您的强制转换策略将JSON转换为PSCustomObject
数组。好主意!也许应该解释一下对@()
的需要(?)。如果输出仅包含一个项,则Get ChildItem不输出数组。若这不是PS,我们需要检查第一个输出的类型,数组和对象,然后相应地处理它。在PS中,(@(@('s','d'))[0].GetType()
是字符串,这意味着创建仅包含一个数组的数组的意图将被忽略。在本例中,如果第一行只生成一个项,并且未使用@(),则$items将是一个对象,并且尝试将数组连接到对象将导致第二行出错@()第二行不需要,因为您可以通过相同的+=
@papo |Get-ChildItem将对象连接到数组,也可以将数组连接到数组。如果输出仅包含一个项,则该项不输出数组。
但是,它可以工作(至少在我的系统上,PS v5.1.14393.3471)。我可以毫无问题地做到这一点:$Files=@(gci-Filter“$BuildName-$SemanticVersion*.nupkg”)$文件+=@(gci-Filter“Setup.exe”)$Files
@InteXX抱歉没有提及我的评论是对Peter评论的回答。您的示例与Keith相似,所以应该是这样的,但是如果您像Peter所问的那样省略@(),它可能会行为不端。PS的自动类型很好,但可能会产生问题。如果需要数组,请具体说明。或者,您可能最终会出现错误,或者在不同的情况下,您可能会遇到一个数组条目数组,而这是不需要的。我遵循规则,如果是剧本,就要非常简洁。@papo |啊,好的。明白了。这是有道理的。事实上,我最终选择了罗曼的版本,从下面开始<代码>$Files=@(gci-Path$ReleaseDirectory-Filter“$BuildName-$SemanticVersion*.nupkg”;gci-Path$ReleaseDirectory-Filter“Setup.exe”gci-Path$ReleaseDirectory-Filter“release”)$文件简洁美观,效果极佳。
# Collect the results by two or more calls of Get-ChildItem
# and perhaps do some other job (but avoid unwanted output!)
$result = .{
# Output items
Get-ChildItem C:\TEMP\_100715_103408 -Recurse
# Some other job
$x = 1 + 1
# Output some more items
Get-ChildItem C:\TEMP\_100715_110341 -Recurse
#...
}
# Process the result items
$result
$items = get-childitem '\\server\C$\Program Files (x86)\Data1\','\\server\C$\Web\DataStorage\' -Recurse