2

foo | bar > out.txt would normally save the output to out.txt.

However, if foo fails, then clearly bar cannot have any output, so it makes no sense to create out.txt. However, usually the result is that when foo fails an empty out.txt gets created.

I use this type of command often in Makefiles where the problem gets compounded: Once you create the empty file, the make command stops working, because make sees the empty file and decides it's not necessary to create it again.

Is there a way to make out.txt not get created if the pipeline never reaches bar?

0

2 Answers 2

3

For the case of a Makefile, always create it as a temporary file and then rename it.

out.txt: in.txt
       set -o pipefail ; foo $< | bar > [email protected]
       mv [email protected] $@

(Use tabs rather than spaces of course).

This can be expanded to act as a shortcut in the building process

out.txt: in.txt
       set -o pipefail ; foo $< | bar > [email protected]
       cmp -s [email protected] $@ || mv -f [email protected] $@

If the generated out.txt file is unchanged then the modification time is not updated, and this means that things which depend on the unchanged out.txt need not be rebuilt.

2
  • This assumes SHELL is set to bash in the Makefile, right? For pipefail to be a valid shell option.
    – Kusalananda
    Dec 30, 2021 at 16:48
  • Yes it does assume that $SHELL supports pipefail. If you would like to ask a question on how to do this without such a shell I would be happy to answer.
    – icarus
    Dec 30, 2021 at 22:12
0

Does this help:

foo_output="$(foo)"
test -n "${foo_output-}" && bar_output="$(bar <<< $foo_output)"
test -n "${bar_output-} && echo "$bar_output" > output
1
  • It would be better to use a tempory file for the output of food rather than store the data in the shell's memory space. It avoids boundary cases with the output of foo not ending in a newline but not being empty.
    – icarus
    Dec 30, 2021 at 6:49

Not the answer you're looking for? Browse other questions tagged .