Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PowerShell ForEach $file in $Files

Tags:

I have a PowerShell script that gets a file listing and moves the files that meet a specific criteria. Why does the foreach loop run even if the object is empty?

I would assume if $i did not exist it would not run. But if there are no results in $filePath why does the forEach loop run once? I have worked around my issue, but I am curious and I tried searching, but I could not find the answer.

To get this to work I just check to make sure $filePath exists before the forEach loop.

For example, if ($filePath){...

 $filePath = Get-ChildItem -Path $sourceDir | Where-Object {! $_.PSIsContainer -AND ($_.Name -Match "^XXX_XXX*" -OR $_.Name -Match "^YYY_XX*")}   ForEach($i in $filePath){      $sfName =  $i.Name      $sfDir = $i.Directory      $tFileName = testFile $destDir $sfName      $sFile = $sourceDir + $sfName      $tFile = $destDir + $tFileName       moveFile $sFile $tFile 
like image 408
Bagger Avatar asked Apr 03 '15 22:04

Bagger


People also ask

How do I break a foreach loop in PowerShell?

Using break in loopsWhen a break statement appears in a loop, such as a foreach , for , do , or while loop, PowerShell immediately exits the loop. A break statement can include a label that lets you exit embedded loops. A label can specify any loop keyword, such as foreach , for , or while , in a script.

How do I read all files in a directory in PowerShell?

Like the Windows command line, Windows PowerShell can use the dir command to list files in the current directory. PowerShell can also use the ls and gci commands to list files in a different format.

How do I iterate through a text file in PowerShell?

If you have a text file with data you wish to use, you can use PowerShell Get-Content to list the contents of the file. Then use the PowerShell ForEach loop to iterate through the file line by line.


1 Answers

This is a classic issue that has been fixed in PowerShell V3 IIRC. PowerShell's foreach loop will allow you to iterate over a scalar value e.g.:

foreach ($i in 1) {$i} 

That is handy because many times the collection you iterate can contain 0, 1 or N items e.g.:

$files = Get-ChildItem c:\temp\*.txt foreach ($file in $files) {$file} 

In this case, Get-ChildItem could return 0, 1 or N files. N files is great, we can iterate over that. However if it returned 1 file and then you had to stick that one file in an array so that you could use foreach - well that would kind of suck. So foreach allows you to iterate over a scalar object. The problem occurs when Get-ChildItem returns 0 objects. In that case, an empty array is not assigned to $files. Instead $null is assigned. PowerShell considers $null a scalar and hence the foreach loop will execute once where the iterated value is $null. That kind of sucks. And I and many other folks told the team this early on, so in V3 they changed foreach to not iterate a scalar if the value is $null.

Another way to work around this in V1/V2 is to ensure the empty case generates an empty array instead of $null. You can do that using an @() array expression e.g.

$files = @(Get-ChildItem c:\temp\*.txt) foreach ($file in $files) {$file} 

This will work for 0, 1, and N files. It's works for 0 files because the @() will result in an empty array being assigned to $files. foreach will not execute its body when looping over an empty array.

like image 190
Keith Hill Avatar answered Oct 02 '22 15:10

Keith Hill