4

How can i combine these two commands ps aux | head -n1 ; ps aux | grep vlc into one command? I tried to use tee command (ps aux | tee >(head -n1) >(grep vlc)) but it didn't work!

  • 1
    What exactly are you trying to do? – Carl H Sep 15 '15 at 14:38
  • 1
    @CarlH : Exactly what Oil just posted! – HBS Sep 15 '15 at 14:40
  • 2
    @HBS -1: So we have to read the answer to figure the question? – muru Sep 15 '15 at 16:58
  • 2
    @muru: Oftentimes, beginners at new fields do not know how to ask questions as clearly or concisely as experts. Some might say this defines a beginner, since even experts are always asking questions. On Stack Exchange, it seems commonplace for an expert, upon seeing a confusingly worded question, to ask What are you trying to do? to prompt the asker to reword their question. In this case, Oli was able to interpret HBS's question when Carl H wasn't. Instead of clarifying his question, as HBS was prompted to do, he instead pointed to the answer, which should resolve Carl H's uncertainty. – user1717828 Sep 15 '15 at 19:12
  • 4
    @user1717828 so? Hbs won't even try to improve his question, and your justifying that? – muru Sep 15 '15 at 19:15
19

So you're trying to preserve the head of the PS command (so you can see the headers) but only show vlc commands.

I'd personally just use awk and filter based on two conditions, the line number and the VLC. If either are true, we output the line:

$ ps aux | awk 'NR==1 || $11~/vlc/'
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
oli       4833  0.6  0.2 795220 62952 ?        Sl   15:37   0:00 /usr/bin/vlc

It has the added advantage that you're only running ps once. And because field 11 is the main command (not any of its arguments), we won't capture the awk command being run either. We just get VLC and the column headers.


On a sidebar, something like this should work... but doesn't...

ps aux | tee >(head -1 >&2) | grep vlc

You were close, you needed to pipe into the last command or tee will sploodge over STDOUT, and if you output to STDOUT and then pipe, chances are it'll be caught up in the latter grep. In the above I output the headers into STDERR (2) to stop grep interfering with it. Bit hacky but hey-ho.

But yes, this still doesn't work. The reason is that head closes STDOUT, which filters back to tee and arrests the grep. This is by design so head doesn't process more input than it needs to. You can simulate what it's doing with awk:

$ ps aux | tee >(awk 'NR==1 {print;exit}' >&2) | grep "grep"
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND

This is equivalent to head -1. It finds the first line and then exits. This kills off the input buffer, and tee flips out.

Here's a version where awk doesn't quit after it finds the first line. It'll keep running (good thing or not) over every line:

$ ps aux | tee >(awk 'NR==1' >&2) | grep "grep"
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
oli      15103  0.0  0.0  11752  2236 pts/18   S+   11:32   0:00 grep --color=auto grep

Another alternative is sending the input into sponge. Sponge soaks up the whole input stream before writing it to a file (or being redirected). This stops head killing off the parent stream but it does mean the input will be reversed (the grep will output first) so we'll push that through a sponge instance too:

$ ps aux | tee >(sponge >(head -1 >&2)) | sponge >(grep "grep")
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
oli      14875  0.0  0.0  11752  2192 pts/18   S    11:19   0:00 grep --color=auto grep

But while these second two both work, and you're only generating ps aux output once, they still both have serious issues. The awk|grep is processing everything twice and the sponge orgy is buffering everything twice.

tl;dr: If you can process it all in one command like you can with awk, why wouldn't you?

8

You can tell ps to print only the process IDs of vlc with -C.

From man ps:

   -C cmdlist
          Select by command name.  This selects the processes whose
          executable name is given in cmdlist.

Example:

$ ps u -C vlc
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
sylvain  12586  0.1  0.3 1076848 60908 ?       Sl   20:10   0:00 /usr/bin/vlc
7

Use bash process substitution and cat :

cat <(ps aux | head -1) <(ps aux | grep '[v]lc')

The process substitution pattern <() replaces the output of the command inside it as a file. cat will simple concatenate the files as usual.

Example :

$ cat <(ps aux | head -1) <(ps aux | grep '[v]lc')
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
chayan   26031  2.3  0.4 1098532 38556 pts/31  Sl   20:45   0:00 vlc
  • 3
    That's doing essentially the same thing as in the OP's question, but adds an useless cat. – Paused until further notice. Sep 15 '15 at 22:35
  • 1
    You are doing it the other way round than the OP. I think that it is apparent that the OP wanted to run just a single instance of the source of the data - ps aux. – pabouk Sep 16 '15 at 16:14
6

I would use

ps aux | grep -E '^USER|vlc'

you can add | grep -v grep to exclude the grep line

  • 3
    i would suggest to search for something unique like %MEM, %CPU rather than USER as USER itself is a valid username.. – heemayl Sep 15 '15 at 14:52
6

Just tell ps to only show the output for vlc:

$ ps -P $(pgrep vlc)
PID PSR TTY      STAT   TIME COMMAND
6728   2 pts/0    Sl     0:00 vlc

pgrep lists the PIDs of any processes whose name matches the pattern given. ps's -P switch lets you list info only for specific PIDs. Combining the two gives you the ps header and only the lines you care about.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.