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

Powershell foreach loop not parsing variable as expected

Posted on 2010-08-25
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

Accepted Solution

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

That should do it!

Assisted Solution

RyanAndres earned 100 total points
ID: 33527966

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

LVL 70

Assisted Solution

by:Chris Dent
Chris Dent earned 300 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:\"


Does Powershell have you tied up in knots?

Managing Active Directory does not always have to be complicated.  If you are spending more time trying instead of doing, then it's time to look at something else. For nearly 20 years, AD admins around the world have used one tool for day-to-day AD management: Hyena. Discover why


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 70

Assisted Solution

by:Chris Dent
Chris Dent earned 300 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 poshcode.org.

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 70

Assisted Solution

by:Chris Dent
Chris Dent earned 300 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

Is Your AD Toolbox Looking More Like a Toybox?

Managing Active Directory can get complicated.  Often, the native tools for managing AD are just not up to the task.  The largest Active Directory installations in the world have relied on one tool to manage their day-to-day administration tasks: Hyena. Start your trial today.

Question has a verified solution.

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

This script checks a path to see if a folder exists. If the folder does exist you will get output "The folder has previously been created. No action taken" If not it will create the folder. Then adds one user modify permission to the folder. It …
"Migrate" an SMTP relay receive connector to a new server using info from an old server.
With Secure Portal Encryption, the recipient is sent a link to their email address directing them to the email laundry delivery page. From there, the recipient will be required to enter a user name and password to enter the page. Once the recipient …
In an interesting question (https://www.experts-exchange.com/questions/29008360/) here at Experts Exchange, a member asked how to split a single image into multiple images. The primary usage for this is to place many photographs on a flatbed scanner…

860 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