Dzerlig
Dzerlig

Reputation: 247

How do I display git output in bash and store one string from the output in a variable?

I am running git push command in bash which generates some errors.

RESPONSE=$(git push "$target" --all | grep "error:" || true)

generates an output on the screen but variable $RESPONSE is empty

If I change the command to do this:

RESPONSE=$(git push "$target" --all 2>&1 | grep "error:" || true)

command runs silently but actually captures needed error in $RESPONSE

echo $RESPONSE

error: failed to push some refs to 'ssh://[email protected]:7999/test/test-test.git'

I really need to run this git push command in a way that it would hold the error above in $RESPONSE yet generate the entire output on the screen.

Running

RESPONSE=$(git push "$target" --all 2>&1 | tee -a log | grep "error:" || true) did not help, unless I am missing something.

Upvotes: 2

Views: 2546

Answers (2)

Mark Adelsberger
Mark Adelsberger

Reputation: 45819

One solution is to use tee; just not exactly the way you showed. Taking it step by step will perhaps make the solution easier to understand:

git push "$target" --all

will send the error you want to STDERR. That's why you added 2>&1, to redirect STDERR to STDOUT.

git push "$target" --all 2>&1

Then your pipeline (grep, etc.) is able to pick it up and eventually the variable capture is able to see it when you do

RESPONSE=$(git push "$target" --all 2>&1 | grep "error:" || true)

But because the error is no longer going to STDERR, and STDOUT is now being captured instead of sent to the screen, the output disappears.

So what you want to use tee for, is to put the output on both STDERR (for the screen) and STDOUT (for your pipeline and eventual variable capture).

RESPONSE=$(git push "$target" --all 2>&1 |tee >(cat 1>&2) | grep "error:" || true)

This will likely work as you intend, but be aware that everything you see on the screen - all output from the git command, error or otherwise - is now being passed on STDERR.

There aren't many practical reasons why this would be better than the answer about capturing to the variable and then echoing the variable (per miimote's answer), but if for some reason the non-sequential command structure seems better to you, this is a way to do it.

Upvotes: 4

miimote
miimote

Reputation: 383

The first line

RESPONSE=$(git push "$target" --all | grep "error:" || true)

stores the response of the command in the var RESPONSE. So it is done in bash for any construction like VAR=$(command). If exists an error the var is empty but generates an output for the user. If you add 2>&1, you are saying the same but if exists an error the output is the file $1, in your case the var $RESPONSE. You could do this

RESPONSE=$(git push "$target" --all 2>&1 | grep "error:" || true); echo $RESPONSE

You can read more about command substitution and redirections

Upvotes: 1

Related Questions