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!
-
1What 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
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?
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
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
-
3That'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 -
1You 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
I would use
ps aux | grep -E '^USER|vlc'
you can add | grep -v grep
to exclude the grep line
-
3i would suggest to search for something unique like
%MEM
,%CPU
rather thanUSER
asUSER
itself is a valid username.. – heemayl Sep 15 '15 at 14:52
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.