Search code examples
linuxbashtee

bash process substitution can't work fine with tee


The real thing I want to do is like ps -ef|head -n1 && ps -ef|grep httpd. The output should be something like this.

UID        PID  PPID  C STIME TTY          TIME CMD
xxxxx     6888  6886  0 16:49 pts/1    00:00:00 grep --color=auto httpd
root     10992     1  0 13:56 ?        00:00:00 sudo ./myhttpd
root     10993 10992  0 13:56 ?        00:00:00 ./myhttpd
root     11107 10993  0 13:56 ?        00:00:00 ./myhttpd
root     12142 10993  0 14:00 ?        00:00:00 ./myhttpd
root     31871 10993  0 15:03 ?        00:00:00 ./myhttpd

But I hate duplicates. So, I want ps -ef to appear only once.
Considering bash process substitution, I tried ps -ef | tee > >(head -n1) >(grep httpd), but the only output is

UID        PID  PPID  C STIME TTY          TIME CMD

However, ps -ef | tee > >(head -n1) >(head -n2) can work fine in the following way

UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 13:36 ?        00:00:00 /sbin/init
UID        PID  PPID  C STIME TTY          TIME CMD

Can anyone help me ?


Solution

  • You can do head and grep on the same stream.

    ps -ef | (head -n 1; grep '[h]ttpd')
    

    It might be marginally more efficient to refactor to use sed:

    ps -ef | sed -n -e '1p' -e '/[h]ttpd/p'
    

    ... but not all sed dialects deal amicably with multiple -e options. Perhaps this is more portable:

    ps -ef | sed '1b;/[h]ttpd/b;d'
    

    Also note the old trick to refactor the regex so as not to match itself by using a character class.