Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17


Powershell foreach loop not parsing variable as expected

Posted on 2010-08-25
Medium Priority
Last Modified: 2012-05-10
I know this should be easy, but I am very new at powershell
So, Here is the script:

$all_dir = "D:\ C:\"

foreach($folder in $all_dir)

    Write-Host "Folder is " $folder

What I expected for out put is

Folder is  D:\
Folder is  C:\

What I got is :

Folder is  D:\ C:\

Question by:bdorsey63
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions

Accepted Solution

dm7941 earned 400 total points
ID: 33527672
$all_dir = "D:\ C:\"
$all_dir = "C:\","D:\"

That should do it!

Assisted Solution

RyanAndres earned 400 total points
ID: 33527966

$all_dir = @()
$all_dir[0] = "D:\"
$all_dir[1] = "C:\"

LVL 71

Assisted Solution

by:Chris Dent
Chris Dent earned 1200 total points
ID: 33529215

The first answer is right on the nose :) I only wanted to flesh out the explanation a little bit. If you go for accepting anything you should consider the first as it is correct.

This is a string:

$all_dir = "D:\ C:\"

You won't get anything more than one iteration if you use that in a ForEach Loop. For example:

$all_dir = "D:\ C:\"
$i = 1
ForEach ($Object in $all_dir) {
  Write-Host "Loop $i : $Object"

Using this will tell you you have a String (Name field):


These two are equivalent and both give you an array of Objects:

$all_dir = @("C:\", "D:\")
$all_dir = "C:\", "D:\"


Now you can loop because you have something to loop through :)

You can take your original and Split it on the space which will give you an Array:

$all_dir = "D:\ C:\"
$i = 1
ForEach ($Object in $all_dir -Split ' ') {
  Write-Host "Loop $i : $Object"

But if you have a choice it would be neater to define it as an array in the first place.

Ryan, I'm afraid yours won't play, it'll throw an indexing error.

$all_dir = @()
# This will error with "Array assignment failed because index '0' was out of range.":
$all_dir[0] = "C:\"

You can add elements like this:

$all_dir = @()
$all_dir += "C:\"
$all_dir += "D:\"

But you can't index into elements that don't already exist. To use the method as is you'd have to define an array size:

$all_dir = New-Object Object[] 2
$all_dir[0] = "C:\"
$all_dir[1] = "D:\"


Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.


Author Comment

ID: 33530595
Thanks for the answers. I get it, PS recognizes that I have an array element but only one, it does not recognize that it is actual two element, I need to delcare, or be more specific with the array elements.

I am going to increase my points because I have an extend question, and you are all deserving! :-)

If I put this in an text file, say an ini with sections:

all_dir=c:\ d:\

file_type=*.txt, *.xls?

Now I want to read the  those variables values in differing sections, and place into an array, which I will then use the foreach loop.

I was thinking of using Get-Content, but is there a cmdlet which recognizes/works with ini files?

LVL 71

Assisted Solution

by:Chris Dent
Chris Dent earned 1200 total points
ID: 33530675

I'm not aware of an ini file parser, although I wouldn't be entirely surprised to find one kicking around on

Anyway, if you're reading from the file then you must Split the all_dir string to make it into an array.

Get-Content "something.ini" | ForEach-Object {
  If ($_ -Like "all_dir*") {
    $all_dir = ($_ -Replace 'all_dir=') -Split ' '

ini isn't going to be the simplest format to work with. What are you hoping to achieve by using the file?


Author Comment

ID: 33537696

I am just learning powershell. So, this little project is about copy or sync data between a couple of locations. I want to have a friendly text file, which a user could add directories and file types. THne the code will read the the text (ini) file. For directory which are in the all_dir, it would get every file in the directory and all sub-directory.  For directories in in the include, it would grab all files matching the file type and ignoring all other files. If a directory name is in the exclude_dir, then it it would supersede the include and NOT get any files in the excluded directories.  and finally, it would check all the individual files for matches in the destination, look for date differences, perhaps perform a checksum for tell if it is a match, and if not copy over the files.

The whole idea is to teach me powershell  how to loop thru arrays, manipulate arrays, and read, write files and logging. (I know a bit of bash and perl.)
LVL 71

Assisted Solution

by:Chris Dent
Chris Dent earned 1200 total points
ID: 33539755
Good morning,

The easiest format to work with would be CSV. For example:


The advantage of this format is that you can do this:

Import-Csv "TheFile.csv"

And you instantly have an object with each of those variables available. In addition to that you can include multiple lines in the CSV and you won't have to do any extra hard work to deal with them.

I don't want to give too much away, if I write it for you it kind of defeats the point in you trying to learn it.

So, hints... How deep do you want to go? :)

You will benefit from looking at Sub-Expressions ( $( ... ) ) as this allows you to include complex values in strings (although it is not limited to that). e.g.

$Data = Import-Csv "TheFile.csv"
$String = "Source value: $($Data.Source)"

You should investigate ForEach-Object. I rarely use the simple foreach loop, I find ForEach-Object far more useful as it allows full use of both input and output pipelines.

An MD5 hash can be computed for a file:

C# and PowerShell really aren't very far apart. PS, like C#, is a full Object Oriented .NET language, the syntax isn't hard to switch once you get a handle on it.

(Get-Item Somefile.txt).OpenRead() will give you a FileStream object. The MD5 object can be initialised like this:

New-Object Security.Cryptography.MD5CryptoServiceProvider

The reference for that object is here:

Get-ChildItem is going to do the most work here. Just watch out for the Exclude paramater, it's not quite as easy to get working as it implies.

On balance I'd say that this isn't an easy starter project, but don't let that deter you :)


Author Closing Comment

ID: 33553192
Thanks to all

Featured Post

On Demand Webinar: Networking for the Cloud Era

Did you know SD-WANs can improve network connectivity? Check out this webinar to learn how an SD-WAN simplified, one-click tool can help you migrate and manage data in the cloud.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

The following article is intended as a guide to using PowerShell as a more versatile and reliable form of application detection in SCCM.
My attempt to use PowerShell and other great resources found online to simplify the deployment of Office 365 ProPlus client components to any workstation that needs it, regardless of existing Office components that may be needing attention.
Exchange organizations may use the Journaling Agent of the Transport Service to archive messages going through Exchange. However, if the Transport Service is integrated with some email content management application (such as an antispam), the admini…
Add bar graphs to Access queries using Unicode block characters. Graphs appear on every record in the color you want. Give life to numbers. Hopes this gives you ideas on visualizing your data in new ways ~ Create a calculated field in a query: …

705 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question