I have this code:
Get-ChildItem FOLDERNAMEHERE *.png| ForEach-Object { $_.Name } > fileNames.txt
It prints off a list of file Names, and I want to change it to out just print out an index of numbers instead of Names.
To output sequence numbers starting with 1
(replace $i = 0
with $i = -1
to start with 0
):
Get-ChildItem FOLDERNAMEHERE *.png |
ForEach-Object -Begin { $i = 0 } -Process { (++$i) }
Note that the variable $i
lives on after this command, and, if it preexisted before running the command, effectively changes it, because the script blocks passed to ForEach-Object
run directly in the caller's scope.
The increment assignment operation (++
) is wrapped in (...)
so as to also output the incremented value (assignment statements produce no output by default).
As an aside:
GitHub issue #13772 proposes introducing an automatic index variable for use in pipelines, such as $PSIndex
, which would simplify the solution to:
Get-ChildItem FOLDERNAMEHERE *.png | ForEach-Object { $PSIndex + 1 }
Non-streaming alternative, using ..
, the range operator:
if ($count = (Get-ChildItem FOLDERNAMEHERE *.png).Count) {
1..$count
}
Note: Non-streaming means that the results of the Get-ChildItem
call are collected in full, up front in order to determine the upper limit for the sequence numbers.
Similarly, the 1..$count
range operation collects the elements between the range endpoints in an array up front before beginning to produce visible output. See the comments for a discussion.
In other words: Go with the streaming, ForEach-Object
-based solution if the Get-ChildItem
command produces a lot of output objects and you want to start emitting sequence numbers as quickly as possible.