Select/map each item of a Powershell array to a new array
Asked Answered
S

3

63

I have an array of file names in Powershell, and I would like to prepend a path to each of them and get the result in a new array.

In C# I could do this using Linq...

var files = new string[] { "file1.txt", "file2.txt" };
var path = @"c:\temp\";
var filesWithPath = files.Select(f => path + f).ToArray();

But what is the idiomatic way to do this in Powershell? It looks like there is a foreach syntax I could use, but I figure there must be a more concise, functional way to do it.

Surly answered 18/1, 2012 at 10:54 Comment(0)
K
101

An array in Powershell is declared with @() syntax. % is shorthand for foreach-object. Let's declare an array with all the file names and loop through it with foreach. join-path combines a path and a child path into a single path.

$files = @("file1.txt", "file2.txt")
$pFiles = $files | % {join-path "c:\temp" $_ }
$pFiles

Output:

c:\temp\file1.txt
c:\temp\file2.txt

NB: if the input consists of single an element, foreach will not return a collection. If an array is desired, either use explicit type or wrap the results. Like so,

[array]$pFiles = $files | % {join-path "c:\temp" $_ }
$pFiles = @($files | % {join-path "c:\temp" $_ })
Knorr answered 18/1, 2012 at 11:5 Comment(4)
Thanks a lot, I hadn't seen anything about that % shorthand.Surly
This is good it looks like if the source array only has 1 element than the result will not be an array...is this your understanding?Humanly
@Humanly This is about four years old a question. Please post a new one, so that you'll get more attention from the community.Knorr
@Knorr This question is the top Google result for powershell map array, and yours is the topvoted and accepted answer. If your suggested approach behaves differently when the input is of length 1 (and it seems that it does), then I think that's the kind of thing you should mention in your answer, not brush off to another question.Classical
A
5

Like this:

$a = @("file1.txt","file2.txt")
$b = "c:\temp\"
$c = $a | % { $b + $_ }

I can't figure this w/o a foreach. Sorry

Using the great job from Josh Einstein LINQ for Powershell

you can write this:

$a = @("file1.txt","file2.txt")
$b = "c:\temp\"
$c = $a | Linq-Select -Selector {$b + $_ }

having same results in a LINQ manner but not using a foreach (%).

Abomasum answered 18/1, 2012 at 11:4 Comment(3)
w/o foreach it will be $c = $a | .{process{ $b + $_ }}. It is basically the same but works faster.Nun
@RomanKuzmin thank for this, never use this kind of 'foreach' ! Have you some percent value in faster excecution respect a %? thank youAbomasum
This is very nice. I have never seen this syntax before. Can you please explain a little about the . in front of the {? Is this dot sourcing or something else?Conard
D
5

You could also use the replace operator:

PS> 'file1.txt','file2.txt','file3.txt' -replace '(^.+$)','C:\temp\$1'

C:\temp\file1.txt
C:\temp\file2.txt
C:\temp\file3.txt
Decrepitate answered 18/1, 2012 at 13:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.