I just noticed that some of my CI jobs returned OK even though compilation failed. This was essentially because the bash command called to compile the code, while failing and returning 1, had its output piped through sed
to add some colours etc to the output.
In essence, this boils down to the following
$ false; echo $? # returns 1
$ true; echo $? # returns 0
$ false | sed 's/^/OUTPUT: /' # returns 0 because sed returns 0
$ true | sed 's/^/OUTPUT: /' # returns 0 because sed returns 0
I know that on bash, there's PIPESTATUS
, so I can use ${PIPESTATUS[0]}
to get the exit code of the command ran before the pipe. But how do I make a wrapper around any command so that its output is piped to sed and then the exit code of the command itself is returned (discarding the exit code of sed
)?
To make it really versatile, let's say I want to pipe the output of any command to sed to add a colored prefix before each line of output:
$ PREFIX="$(printf '\033[1;31m')OUTPUT: $(printf '\033[0m')"
$ ls | sed "s/^/$PREFIX/"
As argued above, because of the pipe to sed
, this will return 0 regardless of what ls
returns, and will display the directory contents with each line preceded by a red OUTPUT:
.
Can I define a function, alias etc (let's call it "wrap") to make me call e.g. wrap ls *.txt
in such a way that ls *.txt
is executed, the output piped through the sed pattern, and the exit code of ls *.txt
itself is returned, so that
$ wrap ls *.txt
OUTPUT: file1.txt
OUTPUT: file2.txt
$ echo $? # displays 0 (assuming there is at least one .txt file)
$ wrap ls *.foo
ls: No such file or directory
$ echo $? # displays 1 (assuming there is NO .foo file)