I'm new to PowerShell and ran into confusing behavior when building an array of file paths. A single concatenation works as expected:
$test = $ENV:USERPROFILE + 'NTUSER.DAT'
This produces `C:UsersOwnerNTUSER.DAT`. Putting that expression inside a one-element array also works, and an array containing two concatenated paths appears correct. However, when I add a plain string as the first element, the paths are split apart:
$testarray = @('Alwil Software', $ENV:USERPROFILE + 'NTUSER.DAT', $ENV:LOCALAPPDATA + 'MicrosoftOneDrive')
The resulting elements are `Alwil Software`, `C:UsersOwner`, `NTUSER.DAT`, `C:UsersOwnerAppDataLocal`, and `MicrosoftOneDrive`. Why does adding the first string change how the commas and plus signs are interpreted, and what is the correct way to construct this array?
3 Answers
The comma is the array-element separator, and PowerShell evaluates operators from left to right when they have the same precedence. Once the first comma creates an array on the left, the following `+` operates on that array instead of concatenating two strings. Wrap each concatenation in parentheses so it is evaluated first:
$testarray = @(
'Alwil Software'
($ENV:USERPROFILE + 'NTUSER.DAT')
($ENV:LOCALAPPDATA + 'MicrosoftOneDrive')
)
That produces exactly three elements: the software name and the two complete paths.
The `@(...)` wrapper does not force every expression inside it to be evaluated independently. It collects the result of the whole expression. In the problematic version, the comma is encountered before the later `+` operations finish, so the left-hand operand of `+` can already be an array. PowerShell's `+` behavior depends on the type of its left operand: with a string it concatenates, while with an array it adds elements. Parentheses make the intended evaluation order explicit:
@('Alwil Software', ($ENV:USERPROFILE + 'NTUSER.DAT'), ($ENV:LOCALAPPDATA + 'MicrosoftOneDrive'))
The issue is expression parsing and operator precedence, not console formatting. Checking `.Count` or converting the result to JSON will show that the unparenthesized version really contains five elements.
For filesystem paths, `Join-Path` is generally safer and clearer than manually concatenating strings:
$testarray = @(
'Alwil Software'
(Join-Path $ENV:USERPROFILE 'NTUSER.DAT')
(Join-Path $ENV:LOCALAPPDATA 'MicrosoftOneDrive')
)
You can also use expandable strings such as `"$ENV:USERPROFILENTUSER.DAT"`, but `Join-Path` communicates that these values are paths and handles separators more appropriately.

That fixed it—the array now contains the three expected values, with each path kept intact.