Solved

Powershell foreach loop not parsing variable as expected

Posted on 2010-08-25
8
1,817 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
[X]
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
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 71

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
IoT Devices - Fast, Cheap or Secure…Pick Two

The IoT market is growing at a rapid pace and manufacturers are under pressure to quickly provide new products. Can you be sure that your devices do what they're supposed to do, while still being secure?

 

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
 
LVL 71

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 71

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

NEW Veeam Agent for Microsoft Windows

Backup and recover physical and cloud-based servers and workstations, as well as endpoint devices that belong to remote users. Avoid downtime and data loss quickly and easily for Windows-based physical or public cloud-based workloads!

Question has a verified solution.

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

A recent project that involved parsing Tableau Desktop and Server log files to extract reusable user queries for use in other systems. I chose to use PowerShell to gather the data, and SharePoint to present it...
In this post we will be converting StringData saved within a text file into a hash table. This can be further used in a PowerShell script for replacing settings that are dynamic in nature from environment to environment.
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…
This is my first video review of Microsoft Bookings, I will be doing a part two with a bit more information, but wanted to get this out to you folks.

630 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