Powershell issue when using mkdir command

Viewed 315

I've encountered a strange issue with powershell. When calling the mkdir command with a powershell var it appears that powershell appends to the variable, although this only occurs if inside a function call.

I have the following sample code.

function TestStuff($test) {
    Write-Host "Called with parameter: $test"
    $newPath = Join-Path "C:\testy\" $test
    mkdir $newPath
    # It's ok here
    Write-Host "New path is: $newPath"
    return $newPath;
}

$myNewPath = TestStuff "testVar"
# It's been doubled up here
Write-Host "Returned from function it is: $myNewPath"

This produces the following output

Called with parameter: testVar
New path is: C:\testy\testVar
Returned from function it is: C:\testy\testVar C:\testy\testVar

Buried within a powershell script this issue was tricky to spot. Is anyone able to explain this behaviour. The eventual solution got re-written so it was not a function call. The other alternative was to pipe the output of mkdir to null as follows: mkdir $myPath > null Although this produces a file named null on file system but didn't seem to fiddle with the $myPath var.

1 Answers

I've encountered a strange issue with powershell

No, you've come to learn the true nature of PowerShell.

In PowerShell, any output from any value expression "bubbles up" to the caller, including the output from the mkdir call:

PS C:\> $myNewPath = TestStuff "testVar"
PS C:\> $myNewPath.Count
2
PS C:\> $myNewPath[0].GetType() # the output from `mkdir` is a DirectoryInfo object

IsPublic IsSerial Name                                     BaseType                  
-------- -------- ----                                     --------                  
True     True     DirectoryInfo                            System.IO.FileSystemInfo  

PS C:\> $myNewPath[1].GetType() # this is the string you `return`d:

IsPublic IsSerial Name                                     BaseType                  
-------- -------- ----                                     --------                  
True     True     String                                   System.Object             


To fix your function, either suppress the output from mkdir with Out-Null or by assigning it to $null:

mkdir $newPath |Out-Null
# or
$null = mkdir $newPath
# or 
[void]( mkdir $newPath )

... or simply pass through the results directly from mkdir:

function Test-Stuff {
    param($test)

    Write-Host "Called with parameter: $test"
    $newPath = Join-Path "C:\testy" $test

    # No output suppression, output value will be returned to the caller
    mkdir $newPath

    # Let's ensure that the last call actually succeeded
    if($?){
        Write-Host "New path is: $newPath"
    }
}
Related