Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Powershell - clarification about foreach

Tags:

powershell

I am learning powershell and I need someone to give me an initial push to get me through the learning curve. I am familiar with programming and dos but not powershell.

What I would like to do is listing all files from my designated directory and pushing the filenames into an array. I am not very familiar with the syntax and when I tried to run my test I was asked about entering parameters.

Could someone please enlighten me and show me the correct way to get what I want?

This is what powershell asked me:

PS D:\ABC> Test.ps1
cmdlet ForEach-Object at command pipeline position 2
Supply values for the following parameters:
Process[0]:

This is my test:

[string]$filePath = "D:\ABC\*.*";

Get-ChildItem $filePath | foreach
{
 $myFileList = $_.BaseName;
 write-host $_.BaseName
}

Why was ps asking about Process[0]?

I would want to ps to list all the files from the directory and pipe the results to foreach where I put each file into $myFileList array and print out the filename as well.

like image 564
user1205746 Avatar asked Apr 26 '17 20:04

user1205746


1 Answers

Don't confuse foreach (the statement) with ForEach-Object (the cmdlet). Microsoft does a terrible job with this because there is an alias of foreach that points to ForEach-Object, so when you use foreach you have to know which version you're using based on how you're using it. Their documentation makes this worse by further conflating the two.

The one you're trying to use in your code is ForEach-Object, so you should use the full name of it to differentiate it. From there, the issue is that the { block starts on the next line.

{} is used in PowerShell for blocks of code related to statements (like while loops) but is also used to denote a [ScriptBlock] object.

When you use ForEach-Object it's expecting a scriptblock, which can be taken positionally, but it must be on the same line.

Conversely, since foreach is a statement, it can use its {} on the next line.

Your code with ForEach-Object:

Get-ChildItem $filePath | ForEach-Object {
 $myFileList = $_.BaseName;
 write-host $_.BaseName
}

Your code with foreach:

$files = Get-ChildItem $filePath
foreach ($file in $Files)
{
 $myFileList = $file.BaseName;
 write-host $file.BaseName
}
like image 113
briantist Avatar answered Oct 04 '22 20:10

briantist