Reputation: 473
I have come across an unexpected behaviour when trying to filter a list of directories set in an environment variable array.
When I run this code using a local variable I get the expected result:
$myPath = "C:\temp\"
$myList = 'Folder1', 'Folder2', 'Folder3'
Write-Host "myList: $myList"
Get-ChildItem -Recurse $myPath | Where-Object { $_.PSIsContainer } | Where-Object { $_.Name -in $myList } | Select-Object FullName
i.e.
myList: Folder1 Folder2 Folder3
FullName
--------
C:\temp\Folder1
C:\temp\Folder2
C:\temp\Folder3
However when I replace $myList
with an environment variable $env:yourList
$myPath = "C:\temp\"
$env:yourList = 'Folder1', 'Folder2', 'Folder3'
Write-Host "yourList: $env:yourList"
Get-ChildItem -Recurse $myPath | Where-Object { $_.PSIsContainer } | Where-Object { $_.Name -in $env:yourList } | Select-Object FullName
the result of Get-ChildItem is empty
yourList: Folder1 Folder2 Folder3
.
As you can see from the output above the value set in $env:yourList
is printed identical to the one set in $myList
, so what's so special about environment variables that causes them to be processed differently in Where-Object criteria?
BTW, the same behaviour occurs when using -Include
instead of Where-Object
, i.e.:
Get-ChildItem -Path $myPath -Recurse -Include $env:yourList -Directory
Upvotes: 1
Views: 104
Reputation: 437197
An environment variable is always a single string, so you cannot store arrays in them (or any other data types other than [string]
).
PowerShell stringifies the input array on assignment[1], which means joining the array elements with a space as the separator (or, if defined, the separator stored in preference variable $OFS
), which is why array 'Folder1', 'Folder2', 'Folder3'
turned into single string
'Folder1 Folder2 Folder3'
.
If you really do need an environment variable to store your array - which is normally only needed for communicating values to child processes - you'll have to choose a single-string representation for it on assignment, which you can re-convert to an array on reading the variable; e.g.:
# Assuming the array elements contain no newlines, use newlines
# to separate them.
$env:yourList = ('Folder1', 'Folder2', 'Folder3') -join "`n"
# Later, re-convert the single-string representation to an array.
$env:yourList -split "`n"
[1] As Doug Maurer points out, this automatic to-string conversion happens with any RHS that isn't already of type [string]
, such as with $env:yourList = 42
(assigns string '42'
). In other words: Anything you assign to an environment variable is automatically converted to a (single) string.
Upvotes: 2