1

I am trying to delete a folder using robocopy mirroring like this: Start-Process -FilePath "robocopy.exe" -ArgumentList "$emptyDir $sourcePath /mir /e /np /ns /nc /njs /njh /nfl /ndl" -Wait -PassThru -NoNewWindow but still get a line of output for every deleted file enter image description here

I tried adding >nul 2>&1 as explained in another answer here Start-Process -FilePath "robocopy.exe" -ArgumentList "$emptyDir $sourcePath /mir /e /np /ns /nc /njs /njh /nfl /ndl >nul 2>&1" -Wait -PassThru -NoNewWindow but still get the same output.

  • have you tried piping the entire `Start-Process` line to `Out-Null`? – TheMadTechnician Oct 20 '22 at 18:17
  • @TheMadTechnician, `Out-Null` can never silence the output _from the program_ launched by `Start-Process`, it can only silence `Start-Process` _own_ output (and simply omitting `-PassThru` would make it output nothing). Output from a `Start-Process -NoNewWindow` launched console application can fundamentally not be suppressed in PowerShell, as it writes directly to the console, outside PowerShell's control. – mklement0 Oct 20 '22 at 20:36

2 Answers2

2

Since you're running robocopy in the current console window (-NoNewWindow), synchronously (-Wait), there is no reason to use Start-Process at all - just invoke robocopy directly, which also allows you to use > redirections effectively:

robocopy.exe $emptyDir $sourcePath /mir /e /np /ns /nc /njs /njh /nfl /ndl *>$null

Note:

  • Direct execution makes a program's stdout and stderr output directly available to PowerShell, via its success and error output streams.

  • *>$null is a convenient PowerShell shortcut for silencing all output streams - see about_Redirection.

  • Another benefit of direct invocation is that the external program's process exit code is reported in PowerShell's automatic $LASTEXITCODE variable.

See also:


As for what you tried:

  • You fundamentally cannot suppress output from a process launched with Start-Process -NoNewWindow on the PowerShell side.

  • Trying to silence command output at the source, i.e. as part of the target process' command line with >nul 2>&1, would only work if cmd.exe were the -FilePath argument and you passed a robocopy command to it. > redirections are a shell feature, and robocopy itself isn't a shell.

mklement0
  • 382,024
  • 64
  • 607
  • 775
  • You might want to try to use splatting instead, as this can be a better way to sidestep quoting issues. robocopy won't present too many of them, but other apps will. – Start-Automating Oct 20 '22 at 20:29
  • splatting sidesteps the normal attempt to interpet spacing and quotes within arguments and instead passes each element in the array as an argument. So, yeah, it does help with quoting. _a lot_. Calling apps like FFmpeg, net, or sc would be a lot harder if splatting was not a thing. – Start-Automating Oct 20 '22 at 20:42
1

You can try to pass arguments via splatting, and then use the object pipeline to parse line by line.

In the example below, I'm going to split the arguments into two groups, in case you wanted to change out the options programmatically.

$roboFileArgs = @(
    <#
    If you're sure your argument is already a string or
    a primitive type, there's no need to quote it.
    #>
    $emptyDir
    $sourcePath
)

$roboFlags = "/mir","/e","/np","/ns","/nc","/njs","/njh","/nfl","/ndl"

# We can use splatting to pass both lists of arguments
robocopy.exe @roboFileArgs @roboFlags |
    Foreach-Object { 
    <#
      process output line by line and turn it into objects
      or pipe to Out-Null if you truly don't care.
    #>
    }
Start-Automating
  • 8,067
  • 2
  • 28
  • 47