9

I have this bash shell-script command that causes date to run if make succeeds (terminates with zero exit status) and vice versa:

make && date

but now I want to process its output e.g.

make | sed s/a/A/

If I do

make | sed s/a/A/ && date

date runs even when make fails.

If I instead do

make && date | sed s/a/A/

the sed processes date's output instead of make's.

Would you know of any solution? Thanks!


P.S. I've tried these:

(make | sed s/a/A/) && date

date still runs when make fails.

(make && (date > /dev/null)) | sed s/a/A/

date doesn't run when make succeeds.

2
  • 1
    In the very last case ((make && (date > /dev/null)) | sed s/a/A/) date does run when make succeeds, but you are sending it's output to a black hole, so it has no effect... Commented Sep 9, 2011 at 11:36
  • 2
    have a look at PIPESTATUS Commented Sep 9, 2011 at 11:39

3 Answers 3

10

If you do have a shell with process substitution (bash does, posix shell is not), than

make > >(sed s/a/A/) && date

should do the trick, except bash it does not wait for the sed (it seems zsh does, but I only tried it, not checked the doc), so the output of date can get before the last line of sed output. In plain posix shell, you can use a bit more complicated construct

((make && date >&3) | sed s/a/A/) 3>&1

The date can again run before sed has processed everything, so it's output can again come before the last line of sed output.

If you want the date to only run after the sed has processed everything, your only chance is storing the make status somewhere. Something like:

(make && touch make-succeeded) | sed s/a/A/
rm make-succeeded 2>/dev/null && date

abusing the fact, that if the file does not exist, rm (without -f) will exit with nonzero status and silencing it's error message with redirection. As Fredrik has mentioned though, bash does in fact have a place where it does stash the exits status, so in bash you can:

make | sed s/a/A/
[ 0 -eq $PIPESTATUS[0] ] && date
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks! Wish I could give you a bonus point for taking into account that I'd want the date to appear after the sed output.
8

Turn on pipefail in the make subshell.

(set -o pipefail; make 2>/dev/null | sed s/a/A/) && date

Comments

1

Basically like this;

my_make () {
  local rc
  make >tmp
  rc=$?
  sed s/a/A/ tmp
  rm tmp
  return $rc
}

The temporary file should obviously be handled in a proper way; this is bare-bones in order to focus on the issue at hand. You could probably avoid a temp file altogether if you are clever with file descriptors, but it's Friday and I need more coffee.

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.