Solved

Powershell foreach loop not parsing variable as expected

Posted on 2010-08-25
8
1,783 Views
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:\

0
Comment
Question by:bdorsey63
8 Comments
 
LVL 2

Accepted Solution

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


That should do it!
0
 
LVL 8

Assisted Solution

by:RyanAndres
RyanAndres earned 100 total points
ID: 33527966
or

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

etc...
0
 
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"
  $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
 

Author Comment

by:bdorsey63
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:

[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
6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

 
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 ' '
  }
}
$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
 

Author Comment

by:bdorsey63
ID: 33537696
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
 
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:

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
 

Author Closing Comment

by:bdorsey63
ID: 33553192
Thanks to all
0

Featured Post

How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

Join & Write a Comment

This is a PowerShell web interface I use to manage some task as a network administrator. Clicking an action button on the left frame will display a form in the middle frame to input some data in textboxes, process this data in PowerShell and display…
Synchronize a new Active Directory domain with an existing Office 365 tenant
Here's a very brief overview of the methods PRTG Network Monitor (https://www.paessler.com/prtg) offers for monitoring bandwidth, to help you decide which methods you´d like to investigate in more detail.  The methods are covered in more detail in o…
This demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.

758 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

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now