Oliver
Oliver

Reputation: 29483

bash prepend text to every line printed by commands

I'm trying to find a way to do something like this:

# script.sh:
cmd0
set_prepend "some text"
cmd1
cmd2
cmd3
unset_prepend
cmd4

Then whatever stdout generated by cmd1, 2 and 3, every line will be prepended by "some text". There is no relationship between the commands, and the commands can be anything (ls, cat, awk, whatever):

$ script.sh
cmd0 line1
...
cmd0 lineN0
some text cmd1 line1
some text ...
some text cmd1 lineN1
some text cmd2 line1
some text ...
some text cmd2 lineN2
some text cmd3 line1
some text ...
some text cmd3 lineN3
cmd4 line1
...
cmd4 lineN4

The only way I can think of is far from elegant:

script.sh | prepender 

and for each line received by prepender, it checks the existence of a file; if the file exists, the contents are the text to prepend; and set_prepend would create that file and unset_prepend would remove it. However buffering would interfere with this, so it would have to be turned off, and I'm not sure how to garantee that a line going to stdout will be processed by prepender before the next script cmd is execute (otherwise race condition possible).

Upvotes: 1

Views: 506

Answers (1)

Barmar
Barmar

Reputation: 780808

Use exec to redirect output to a pipe. You'll need to save the old stdout in another FD so you can restore it later.

set_prepend() {
    exec 3>&1 | sed "s/^/$1 /"
}
unset_prepend() {
    exec >&3 3>&-
}

Upvotes: 3

Related Questions