I have this strange observation:
I want to run an expression for as many times as there are files.
Yet, the following script always executes only once, no matter how many files are found by Get-ChildItem
:
(Get-ChildItem -Filter '*.png'), (Get-ChildItem -Filter '*.jpg') |
Sort-Object -Property 'Name' |
ForEach-Object -Begin { $idx = 0 } -Process { ++$idx; $idx; }
If I replace the expression with $_
, all rows are returned as expected:
(Get-ChildItem -Filter '*.png'), (Get-ChildItem -Filter '*.jpg') |
Sort-Object -Property 'Name' |
ForEach-Object -Begin { $idx = 0 } -Process { $_; }
As Mathias points out,
(...), (...)
creates a nested (jagged) array, which is not your intent (the,
operator constructs an array from its operands, even if those operands are themselves arrays).The best way to provide output from multiple commands as pipeline input is to use
&
(or.
, if you need the commands to run directly in the caller's scope) with a script block ({ ... }
), in which, as usual you can separate commands with;
:This approach streams the command output, whereas use of
$(...)
or@(...)
(which in this particular case can be used interchangeably) -$(Get-ChildItem -Filter *.png; Get-ChildItem -Filter *.jpg)
or@(Get-ChildItem -Filter *.png; Get-ChildItem -Filter *.jpg)
- collects all output first and then sends it to the pipeline.An simplified version of your command that makes do with a single
Get-ChildItem
call, using the-Path
parameter's support for multiple wildcard patterns:-Filter
is usually preferable, because it filters at the source, but it only supports one wildcard pattern; while-Path
, which makes PowerShell filter the results, is noticeably slower, the overhead from extraGet-ChildItem
calls may negate that advantage.-Include
/-Exclude
, which also filter on the PowerShell side, but, unfortunately, they do not work as one would intuitively expect: see this answer.Also note the use of
(...)
around++$idx
, which causes the updated value to also be output.