2

I have a command that writes to stdout when it is happy and stderr when it's not. I want to check the exit status of the command and do something with either stdout or stderr.

if ! command >/tmp/stdout 2>/tmp/stderr; then
  // do something with /tmp/stderr
  exit 1
fi

// do something else with /tmp/stdout

It's certainly possible to have just one file instead of two but I would like to get rid of all files, not just one.

Is there a way to avoid the temporary files? I tried with mkfifo and custom file descriptors but I can't make that work.

1

You can use the command substitution $(..) syntax in the if condition and see if the command ran successfully or not and still storing the result of the command both stdout and stderr in a variable

if ! var=$(cmd 2>&1); then
    printf 'process stderr contents from $var'
fi

You can see it working if I simulate the cmd to run as a simple script that does this

# cat temp.sh    
echo foo >&2
exit 1

and if I run the script as

if ! var=$(bash tmp.sh 2>&1); then
    printf '%s\n' 'process stderr contents from $var'
    printf '%s\n' "$var"
fi

The same way you can make it work for capturing stdout if the command substitution is successful which will happen to be in the else clause in the above example. In either cases, manipulating the content of "$var" (ensure the quotes are on) will ensure you are processing the result as if it were stored in a file.

You can further go ahead and quote the command-substitution syntax to not let the shell perform word-splitting on the results. E.g. By doing it as below. It might not be needed for straightforward cases like the one I have showed here, but for cases when the results contain some special shell meta characters

if ! var="$(bash tmp.sh 2>&1)"; then

Note: Question title re-phrased since the first version of the answer has been posted.

5
  • Thank you this solves the question I asked. It doesn't solve the question I wanted to ask though: how to keep stdout and stderr separated and still avoid temporary files? Nov 27 '19 at 7:38
  • @DamienCassou: Your question title and the comment above looks different to me. For the question in the comment, I hope at any point of time, your command could either be successful or fail, in which case the $var contains the content of stdout or stderr.
    – Inian
    Nov 27 '19 at 7:52
  • Considering your new re-phrased title, if you want to pass output to different commands on the success/failure cases, do the if..else construct like I've shown and pass the contents of $var to different commands inside the if and else branches
    – Inian
    Nov 27 '19 at 7:54
  • you are right. My question isn't clear enough. The new title (written by @ctrl-alt-delor) doesn't reflect what I wanted to write but what I wrote and what you answered :-). Nov 28 '19 at 8:14
  • If I could follow your solution and get 2 variables, one for stdout and one for stderr, I would be happy but I'm not sure that's possible. Anyway, if I want this answer, I better open a new question :-). Thank you very much for your help. Nov 28 '19 at 8:17
-1

you can use below code

if [[ $? == 0 ]]
then
command 1>stdout.txt
else
echo "exit code is not successfull"
command 2> stderr.txt
fi
3
  • 2
    How are you handling stdout and stderr? Nov 27 '19 at 7:30
  • corrected the code Nov 27 '19 at 7:36
  • 1
    Did you read the question? (avoiding temporary files), you continue to use them, but make it do something else. Nov 27 '19 at 7:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.