Sometimes it is useful to keep the header of an output of some command while grepping the same output for something else. In the example below, the column information is absent:
1 2 3 4 5 6 7 |
[johndoe@ArchLinux]% ps aux | grep "systemd" root 336 0.0 0.1 107736 23408 ? Ss Apr28 0:52 /usr/lib/systemd/systemd-journald root 353 0.0 0.0 34028 6496 ? Ss Apr28 0:05 /usr/lib/systemd/systemd-udevd systemd+ 534 0.0 0.0 91784 3156 ? Ssl Apr28 0:02 /usr/lib/systemd/systemd-timesyncd dbus 541 0.0 0.0 8284 4404 ? Ss Apr28 8:23 /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation --syslog-only root 544 0.0 0.0 17608 4248 ? Ss Apr28 0:11 /usr/lib/systemd/systemd-logind root 584 0.0 0.0 17068 2224 ? Ss Apr28 0:00 /usr/bin/systemd-tty-ask-password-agent --wall |
The solution is to pipe the STDOUT to head using output duplication of tee via process substitution.
1 2 3 4 5 6 7 8 |
[johndoe@ArchLinux]% ps aux| tee -p >(head -1) | grep "systemd" USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 336 0.0 0.1 107736 23408 ? Ss Apr28 0:52 /usr/lib/systemd/systemd-journald root 353 0.0 0.0 34028 6496 ? Ss Apr28 0:05 /usr/lib/systemd/systemd-udevd systemd+ 534 0.0 0.0 91784 3156 ? Ssl Apr28 0:02 /usr/lib/systemd/systemd-timesyncd dbus 541 0.0 0.0 8284 4404 ? Ss Apr28 8:23 /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation --syslog-only root 544 0.0 0.0 17608 4248 ? Ss Apr28 0:11 /usr/lib/systemd/systemd-logind root 584 0.0 0.0 17068 2224 ? Ss Apr28 0:00 /usr/bin/systemd-tty-ask-password-agent --wall |
This works in BASH, but other POSIX-compliant SHELLs may not have process substitution implemented. The command tee works as a splitter: the data goes to STDOUT and also its duplicate is written to a file ("file.txt" in the example below):
STDOUT of tee is piped into STDIN of grep and instead of file.txt process substitution >(head -1) is used, where temporary file descriptors are created. Although head -1 is an another process, it's STDIN is mapped to STDIN of a temporary file and >(head -1) is treated as a file descriptor.
There is a more POSIX-friendly solution based on pee command from moreutils package:
1 2 3 4 5 6 7 8 9 |
[johndoe@ArchLinux]% sudo pacman -S moreutils [johndoe@ArchLinux]% ps aux| pee 'head -1' 'grep "systemd"' USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 336 0.0 0.1 107736 23408 ? Ss Apr28 0:52 /usr/lib/systemd/systemd-journald root 353 0.0 0.0 34028 6496 ? Ss Apr28 0:05 /usr/lib/systemd/systemd-udevd systemd+ 534 0.0 0.0 91784 3156 ? Ssl Apr28 0:02 /usr/lib/systemd/systemd-timesyncd dbus 541 0.0 0.0 8284 4404 ? Ss Apr28 8:23 /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation --syslog-only root 544 0.0 0.0 17608 4248 ? Ss Apr28 0:11 /usr/lib/systemd/systemd-logind root 584 0.0 0.0 17068 2224 ? Ss Apr28 0:00 /usr/bin/systemd-tty-ask-password-agent --wall |
The pee program pipes the the output of "ps aux" to multiple commands which are listed in pee's input arguments. Note that their execution is done in parallel, so to ensure the desired order of execution you can add a pause between the commands:
1 |
[johndoe@ArchLinux]% ps aux| pee 'head -1' 'sleep 0.25 && grep "systemd"' |
Also you can use grepping capabilities of sed:
1 2 3 4 5 6 7 8 |
[johndoe@ArchLinux]% ps aux| sed --quiet '1p;/systemd/p' USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 336 0.0 0.1 107736 23408 ? Ss Apr28 0:52 /usr/lib/systemd/systemd-journald root 353 0.0 0.0 34028 6496 ? Ss Apr28 0:05 /usr/lib/systemd/systemd-udevd systemd+ 534 0.0 0.0 91784 3156 ? Ssl Apr28 0:02 /usr/lib/systemd/systemd-timesyncd dbus 541 0.0 0.0 8284 4404 ? Ss Apr28 8:23 /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation --syslog-only root 544 0.0 0.0 17608 4248 ? Ss Apr28 0:11 /usr/lib/systemd/systemd-logind root 584 0.0 0.0 17068 2224 ? Ss Apr28 0:00 /usr/bin/systemd-tty-ask-password-agent --wall |
Another alternative is awk. Print the line if it contains "systemd" or if the number of rows is equal to 1:
1 2 3 4 5 6 7 8 |
[johndoe@ArchLinux]% ps aux| awk '{ if $0 ~ /systemd/ || NR == 1 ) print $0}' USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 336 0.0 0.1 107736 23408 ? Ss Apr28 0:52 /usr/lib/systemd/systemd-journald root 353 0.0 0.0 34028 6496 ? Ss Apr28 0:05 /usr/lib/systemd/systemd-udevd systemd+ 534 0.0 0.0 91784 3156 ? Ssl Apr28 0:02 /usr/lib/systemd/systemd-timesyncd dbus 541 0.0 0.0 8284 4404 ? Ss Apr28 8:23 /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation --syslog-only root 544 0.0 0.0 17608 4248 ? Ss Apr28 0:11 /usr/lib/systemd/systemd-logind root 584 0.0 0.0 17068 2224 ? Ss Apr28 0:00 /usr/bin/systemd-tty-ask-password-agent --wall |