Background
This is a pretty handy trick to know when you want to filter out the command you’re running, so that it’s not included in ps output. This proves handy when writing a shell script that needs to parse output from ps.
NOTE: The command ps, allows you to see all the processes being run on a UNIX/Linux system. You typically use it with the switches “-eaf” or “-ef”.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | # columns description: # UID = user who owns the process # PID = process # # PPID = parents' process # # C = # STIME = start time # TTY = terminal type (has to do with which shell command ran from) # TIME = system time its run # CMD = command (aka. program name) % ps -eaf UID PID PPID C STIME TTY TIME CMD root 1 0 0 2008 ? 00:24:46 init [5] root 2 0 0 2008 ? 00:00:00 [kthreadd] root 3 2 0 2008 ? 00:01:58 [migration/0] root 4 2 0 2008 ? 00:23:13 [ksoftirqd/0] root 5 2 0 2008 ? 00:00:00 [watchdog/0] root 6 2 0 2008 ? 00:02:35 [migration/1] root 7 2 0 2008 ? 00:09:55 [ksoftirqd/1] root 8 2 0 2008 ? 00:00:00 [watchdog/1] root 9 2 0 2008 ? 00:06:36 [events/0] root 10 2 0 2008 ? 00:06:16 [events/1] root 11 2 0 2008 ? 00:00:10 [khelper] root 54 2 0 2008 ? 00:19:26 [kblockd/0] |
Problem
Here’s an example where we want to see if a program is running, so we grep the output of ps like so:
1 2 3 4 5 6 7 8 9 10 11 | % ps -eaf | grep httpd root 2683 1 0 2008 ? 00:20:31 /usr/sbin/httpd user1 13188 3984 0 12:45 pts/1 00:00:00 grep httpd apache 17146 2683 0 Aug30 ? 00:00:02 /usr/sbin/httpd apache 17147 2683 0 Aug30 ? 00:00:02 /usr/sbin/httpd apache 17149 2683 0 Aug30 ? 00:00:02 /usr/sbin/httpd apache 17150 2683 0 Aug30 ? 00:00:02 /usr/sbin/httpd apache 17151 2683 0 Aug30 ? 00:00:02 /usr/sbin/httpd apache 17152 2683 0 Aug30 ? 00:00:02 /usr/sbin/httpd apache 17153 2683 0 Aug30 ? 00:00:02 /usr/sbin/httpd apache 17154 2683 0 Aug30 ? 00:00:02 /usr/sbin/httpd |
The problem? Notice that a portion of our command, “grep httpd” is polluting our ps output. How can we get rid of it?
The Trick
You can alter what you are grepping for, without actually altering the results, by using a benign regular expression.
1 2 3 4 5 6 7 8 9 10 | % ps -eaf | grep "[h]ttpd" root 2683 1 0 2008 ? 00:20:31 /usr/sbin/httpd apache 17146 2683 0 Aug30 ? 00:00:02 /usr/sbin/httpd apache 17147 2683 0 Aug30 ? 00:00:02 /usr/sbin/httpd apache 17149 2683 0 Aug30 ? 00:00:02 /usr/sbin/httpd apache 17150 2683 0 Aug30 ? 00:00:02 /usr/sbin/httpd apache 17151 2683 0 Aug30 ? 00:00:02 /usr/sbin/httpd apache 17152 2683 0 Aug30 ? 00:00:02 /usr/sbin/httpd apache 17153 2683 0 Aug30 ? 00:00:02 /usr/sbin/httpd apache 17154 2683 0 Aug30 ? 00:00:02 /usr/sbin/httpd |
Explanation
By re-encoding what we are looking for from httpd to [h]ttpd we’ve altered it by utilizing grep’s capability to use regular expressions. Regular expressions provide us the ability to use short-handed notations to represent patterns of text. Most people should be somewhat familiar with this capability when using the command ls to list files. The command ls can be used to find all the files that start with the letter a by utilizing a wildcard regular expression, aka. the asterisk character, aka. star, aka. *.
1 2 3 4 5 6 7 8 9 10 11 12 | # wildcard examples % ls afile1 afile2 afile3 bfile1 bfile2 bfile3 cfile1 cfile2 cfile3 # example 1 % ls a* afile1 afile2 afile3 # example 2 % ls b* bfile1 bfile2 bfile3 |
Now lets say we want to create a single command that provides us with the list of ALL the files that start with an a or b. The bracket notation [ ] regular expression allows you to list sets of characters. So for example:
1 2 3 4 5 6 7 8 9 10 11 12 | # set examples % ls afile1 afile2 afile3 bfile1 bfile2 bfile3 cfile1 cfile2 cfile3 # example 1 % ls [ab]* afile1 afile2 afile3 bfile1 bfile2 bfile3 # example 2 % ls [bc]* bfile1 bfile2 bfile3 cfile1 cfile2 cfile3 |
So back to our ps example. What does the bracket notation regular expression provide us here? This is the trick. By telling grep that we are looking for [h]ttpd, we’ve encoded our grep query to look like this: [h]ttpd, while what we’re actually grepping for to be: httpd. Since [h]ttpd doesn’t match httpd at the literal string level, grep will effectively ignore itself as being a match in the ps output.
A pretty neat [t]rick.
NOTE: For further details regarding my one-liner blog posts, check out my one-liner style guide primer.

pgrep(1) does the trick and many more and is very nice to use in scripts etc. Because its output is much better to parse.