0

I want to assign to a variable the error message printed by an xcopy command from a powershell script. If I simply assign the command to a variable, it only saves the last line, where it says the number of files copied

> $out = xcopy C:\test.txt C:\
File not found - test.txt
> $out
0 File(s) copied

I want to save the error message, meaning the string "File not found".

I already tried all methods suggested here How to show output of xcopy in powershell script while it's running, but also piping it to Tee-Object -Variable out only saves the last line of the output and not the error message (same as above).

The closest I got was by using redirection xcopy C:\a.txt C:\ 2>&1 | Out-Host , but this still doesn't save it to a variable of my choice, only to the global $error[0] variable

My desired output would be a string with the error message. In the above example:

> $out
File not found - test.txt
2
  • $xcoutput = (xcopy C:\TEST.TXT C:\ 2>&1)? Commented Apr 12, 2024 at 19:35
  • wow that was easy, thanks. So I can access the error message by [string]$xcoutput[1]. If you post it as answer I'll mark it as the solution. Anyway, now i am more interested in understanding the reason behind this behaviour... What difference do the parenthesis do? And why a simple assignment only stores the copy result and not the error message? Commented Apr 12, 2024 at 19:57

2 Answers 2

1

You should use $xcoutput = (XCOPY C:\TEST.TXT C:\ 2>&1).

XCOPY is not a PowerShell cmdlet; it’s what is referred to as an ‘external command’ (implemented via the file XCOPY.EXE). This means that it doesn’t generate PowerShell objects as output; it generates ordinary strings.

If you want to capture the standard output of an external command in a PowerShell variable, simply writing $xcoutput = XCOPY C:\TEST.TXT C:\ will do the trick - but XCOPY also writes to the standard error output, so in order to capture that, you need to redirect the standard error output to the standard output. This is done by XCOPY C:\TEST.TXT C:\ 2>&1 when you don’t want/need to capture it in a variable.

However, it’s not automatically clear whether $capturevariable = XCOPY C:\TEST.TXT C:\ 2>&1 is supposed to redirect the standard error output of XCOPY to the standard output of XCOPY, or whether to redirect the standard error output of the assignment to the standard output of the assignment. The parentheses of $xcoutput = (XCOPY C:\TEST.TXT C:\ 2>&1) clarifies this, and redirects the standard error output of XCOPY to the standard output of XCOPY, then takes the combined output and assigns it to $xcoutput. $xcoutput is now an object of type [string[]], and can be manipulated as such.

(Microsoft Learn has a whole page on PowerShell redirection.)

Sign up to request clarification or add additional context in comments.

Comments

1

From Windows Powershell in Action:

$err = $($output = xcopy c:\test.txt c:\) 2>&1

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.