开发者

Combine the results of two distinct Get-ChildItem calls into single variable to do the same processing on them

I'm trying to write a PowerShell script开发者_运维百科 to build a list of files, from several directories. After all directories have been added to the main list, I'd like to do the same processing on all files.

This is what I have:

$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

which fails with this error:

Cannot convert argument "0", with value: "System.Object[]", for "Add" to type "System.IO.FileInfo": "Cannot convert the "System.Object[]" va lue of type "System.Object[]" to type "System.IO.FileInfo"."

I am mostly interested in what is the correct approach for this type of situation. I realize that my code is a very C way of doing it -- if there is a more PowerShell way to acomplish the same task, I'm all for it. The key, is that the number of $loc#'s may change over time, so adding and removing one or two should be easy in the resulting code.


Not sure you need a generic list here. You can just use a PowerShell array e.g.:

$items  = @(Get-ChildItem '\\server\C$\Program Files (x86)\Data1\' -r)
$items += @(Get-ChildItem '\\server\C$\Web\DataStorage\' -r)

PowerShell arrays can be concatenated using +=.


From get-help get-childitem: -Path Specifies a path to one or more locations. Wildcards are permitted. The default location is the current directory (.).

$items = get-childitem '\\server\C$\Program Files (x86)\Data1\','\\server\C$\Web\DataStorage\' -Recurse


Here is some perhaps even more PowerShell-ish way that does not need part concatenation or explicit adding items to the result at all:

# 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

But the code inside the script block should be written slightly more carefully to avoid unwanted output mixed together with file system items.

EDIT: Alternatively, and perhaps more effectively, instead of .{ ... } we can use @( ... ) or $( ... ) where ... stands for the code containing several calls of Get-ChildItem.


Keith's answer is the PowerShell way: just use @(...)+@(...).

If you actually do want a typesafe List[IO.FileInfo], then you need to use AddRange, and cast the object array to a FileInfo array -- you also need to make sure you don't get any DirectoryInfo objects, or else you need to use IO.FileSystemInfo as your list type:

So, avoid directories:

$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 } )) )

Or use FileSystemInfo (the common base class of FileInfo and DirectoryInfo):

$items = New-Object Collections.Generic.List[IO.FileSystemInfo]
$items.AddRange( ([IO.FileSystemInfo[]](ls '\\server\C$\Program Files (x86)\Data1\' -r)) )
$items.AddRange( ([IO.FileSystemInfo[]](ls '\\server\C$\Web\DataStorage\' -r)) )


-Filter is more performant than -Include, so if you don't have a lot of different extensions, simply concatenating two filtered lists might be faster.

$files  = Get-ChildItem -Path "H:\stash\" -Filter *.rdlc -Recurse 
$files += Get-ChildItem -Path "H:\stash\" -Filter *.rdl  -Recurse 

I compared the output with a timer like this:

$stopwatch = [System.Diagnostics.Stopwatch]::StartNew()
# Do Stuff Here
$stopwatch.Stop()
Write-Host "$([Math]::Round($stopwatch.Elapsed.TotalSeconds)) seconds ellapsed"
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜