I'm using some GIT commands in my PowerShell scripts. Most of the time I'm calling the GIT commands via Invoke-Expression
so that I, eg
At some GIT commands I recognized that not all output is returned via Invoke-Expression
though the documentation states:
Outputs
PSObject
Returns the output that is generated by the invoked command (the value of the Command parameter).
Here is an example:
> $x = iex "git fetch --all"
remote: Enumerating objects: 7, done.
remote: Counting objects: 100% (7/7), done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 4 (delta 3), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (4/4), done.
Content of $x
:
> $x
Fetching origin
Fetching upstream
So the main information is not returned to $x
. I can't imagine that git fetch --all
is returning the main information via stderr
(wouldn't make sense ...).
I also found this PowerShell question , which is unanswered and the used PowerShell version is 2.
Used PowerShell version:
> $PSVersionTable
Name Value
---- -----
PSVersion 6.2.0
PSEdition Core
GitCommitId 6.2.0
OS Microsoft Windows 10.0.18362
Platform Win32NT
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
WSManStackVersion 3.0
How can I force Invoke-Expression
to return the whole output?
Thx
As I mentioned in " PowerShell Capture Git Output ", with Git 2.16 (Q1 2018) , you can try and set first:
set GIT_REDIRECT_STDERR=2>&1
Then in your Powershell script, you should get both stdout and stderr outputs,
See also dahlbyk/posh-git
issue 109 for a more Powershell-like example:
$env:GIT_REDIRECT_STDERR = '2>&1'
VonC's answer works well with git
, specifically, but it's worth discussing a generic solution :
Note: Invoke-Expression
should generally be avoided and there is no reason to use it for invocation of external programs : just invoke them directly and assign to a variable:
$capturedStdout = git ... # capture git's stdout output as an array of lines
As has been noted, git
outputs status information to stderr , whereas data goes to stdout; a PowerShell variable assignment only captures stdout output . [1]
To capture a combination of stdout and stderr , interleaved, as it would print to the terminal, you can use redirection 2>&1
, as in other shells, to merge the error stream / stderr ( 2
) into ( >&
) the data output stream (stdout equivalent, 1
- see about_Redirection ):
$combinedOutput = git fetch --all 2>&1
Caveat : In PowerShell versions up to v7.1, if $ErrorActionPreference = 'Stop'
happens to be in effect, the use of 2>
unexpectedly triggers a terminating error; this problematic behavior is discussed in GitHub issue #4002 .
There are non-obvious differences to the behavior of other shells, however:
The output will be an array of lines , not a single, multi-line string,
Lines that originated from stdout are represented as strings , as expected, but lines originating from stderr are actually [System.Management.Automation.ErrorRecord]
instances, though they print like strings and on conversion to strings do reproduce the original line, such as when sending the result to an external program.
This answer shows how to separate the captured lines by stream of origin (assuming stdout and stderr were merged).
Being able to capture stderr output separately in a variable is desirable, which isn't supported as of PowerShell 7.2.x, however. Adding future support, along the lines of 2>variable:errs
, is the subject of GitHub issue #4332 .
The array-based result can be advantageous for parsing ; eg, to find a line that contains the word unpacking
:
PS> $combinedOutput -match 'unpacking'
Unpacking objects: 100% (4/4), done.
Note: If there's a chance that only one line was output, use @($combinedOutput) -match 'unpacking'
If you prefer to receive a single, multi-line string instead:
$combinedOutput = (git fetch --all 2>&1) -join "`n" # \n (LF); or: [Environment]::NewLine
If you don't mind a trailing newline as part of the string, you can more simply use Out-String
: [2]
$combinedOutput = git fetch --all 2>&1 | Out-String
Caveat : In Windows PowerShell this won't work as expected if stderr lines are present , as they are rendered like PowerShell error records (this problem has been fixed in PowerShell (Core) 6+ ); run cmd /c 'echo data & echo err >&2' 2>&1 | Out-String
cmd /c 'echo data & echo err >&2' 2>&1 | Out-String
to see the problem. Use the -join "`n"
solution to avoid the problem.
Note:
$LASTEXITCODE
variable : By convention (which most, but not all programs observe), 0
indicates success and and any nonzero value failure (a notable exception is robocopy
which uses several nonzero exit codes to communicate additional information in the success case).[1] For comprehensive information on capturing output from external programs in PowerShell, see this answer .
[2] This problematic Out-String
behavior is discussed in GitHub issue #14444 .
试试这个(没有iex)
$x=git fetch --all
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.