12 Sep 2010

PowerShell and Arrays

I came across a strange feature of PowerShell recently.  When dealing with an array that held a single item, I was very surprised to see that the count of items was over 1000.  To illustrate the problem, consider the code below:

		
$files = Get-ChildItem C:\Temp
# Single file present in target folder

Write-Host "Total number of files: $files.Length"
# $files.Length returns value in 1000s
		
for ($i = 0; $i -lt $files.Length; $i++)
{
	$file = $files[$i].Name
	Write-Host "Processing $file"
}

When the code was run for the case when there was single file in the target directory, the count came back in the 1000s. The script then raised an exception for each of the 1000s of times it attempted to reference files[i], when no such array index existed.

It took some digging to realise that what was actually happening was that when PowerShell returns a collection with one or zero items in the collection, it unpacks the array and returns the item (or $null), and not an array.  So in the instance above, by calling $files.Length, the script was returning the length of the file object in bytes, and not the size of the array. 

To correct this behaviour, simply wrap the call generating the array with @(), as shown below:

		
$files = @(Get-ChildItem C:\Temp)

This will have no effect if the call returns an array with more than one item (i.e. you will not have an array wrapped in an array). See this StackTack answer from Keith Hill for a more detailed response:

Also, just to note that the code for this post was highlighted using the Google Code Prettify JavaScript library.

No comments:

Post a Comment