Powershell foreach loop not parsing variable as expected

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:\

bdorsey63Asked:
Who is Participating?

Improve company productivity with a Business Account.Sign Up

x
 
dm7941Connect With a Mentor Commented:
change:
$all_dir = "D:\ C:\"
to
$all_dir = "C:\","D:\"


That should do it!
0
 
RyanAndresConnect With a Mentor Commented:
or

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

etc...
0
 
Chris DentConnect With a Mentor PowerShell DeveloperCommented:

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"
  $i++
}

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

$all_dir.GetType()

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

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

$all_dir.GetType()

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"
  $i++
}

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:\"

Cheers,

Chris
0
Has Powershell sent you back into the Stone Age?

If managing Active Directory using Windows Powershell® is making you feel like you stepped back in time, you are not alone.  For nearly 20 years, AD admins around the world have used one tool for day-to-day AD management: Hyena. Discover why.

 
bdorsey63Author Commented:
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:

[directories]
all_dir=c:\ d:\
include_dir=data
exclude_dir=windows

[files]
file_type=*.txt, *.xls?
file_include=*.dbf

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?

0
 
Chris DentConnect With a Mentor PowerShell DeveloperCommented:

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 ' '
  }
}
$all_dir
$all_dir.GetType()


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

Chris
0
 
bdorsey63Author Commented:
Chirs,

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.)
0
 
Chris DentConnect With a Mentor PowerShell DeveloperCommented:
Good morning,

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

Source,Destination,Exclude,Filter
C:\Stuff,H:\Backup,Images,*.ps1

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:

http://sharpertutorials.com/calculate-md5-checksum-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:

http://msdn.microsoft.com/en-us/library/system.security.cryptography.md5cryptoserviceprovider.aspx

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 :)

Chris
0
 
bdorsey63Author Commented:
Thanks to all
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.