Is there a way to redirect output in bash to different places with different filters?

If I have a process a.outI can do ./a.out | grep footo see stdout a.out filtered by foo. I can also say ./a.out 2>&1 | grep footo see both err and out filtered by foo. Using the command, teeI can send stdout both to the terminal and, possibly, to a file. But is there a way to filter them separately? how in:

./a.out | tee grep foo file.txt

but what goes on file.txtis filtered to match foo, but not what I see on the screen ... or even better than what I see on the screen, is baz filtered instead of foo? If in bash there is no way to do this, I would write my own "tee", but I would suggest that there is some way ...

+5
source share
3 answers

Very simple, just use process substitution for your files:

./a.out | tee >(grep foo > out.txt) | grep baz

Notice also that it teecan take as many arguments as you like, so you can do things like:

./a.out | tee >(grep foo > foo.txt) >(grep bar > bar.txt) [etc]
+3
source

To display everything on the terminal and filter the output to a file, try:

./a.out| tee /dev/tty | grep foo > file

If you are on a system with the / proc file system (e.g. linux), you can filter the output to your terminal using:

{ ./a.out | tee /proc/self/fd/3 | grep foo > file; } 3>&1 | grep bar

But even this is probably too complicated. Just do the following:

./a.out | awk '/foo/{ print > "file" } 1' | grep bar
+3
source
{ { ( myCommandThatOutputsOnStdOutandStdErr; ) \
| ( awk ' ... filters stdout ... ' - ; ) >&3; } 2>&1 \
| ( awk ' ... filters stderr ... ' - ; ) >&4; } 3>&1 4>&2

. awk , . , stderr stdout , , stdout stdout, stderr stderr.

3>&1 4>&2 , 3>my.stdout 4>my.stderr.

+2

All Articles