When I search for some process that doesn't exist, e.g.

$ ps aux | grep fnord                          
wayne    15745  0.0  0.0  13580   928 pts/6    S+   03:58   0:00 grep fnord

Obviously I don't care about grep - that makes as much sense as searching for the ps process!

How can I prevent grep from showing up in the results?

  • 35
    If you need only the PID of a process, you can replace ps aux |grep with pgrep (or pgrep -f ).
    – jofel
    Apr 30 '13 at 13:54
  • 7
    Same question on Serverfault and Superuser.
    – Thor
    Apr 30 '13 at 14:08
  • is that output legit? it seems that there IS no program named fnord running...
    – acolyte
    Apr 30 '13 at 17:10
  • 4
    @acolyte, that's precisely it - but because it's piping the output into grep, grep is running (waiting for the output of ps aux, I expect). So the question is how to prevent grep fnord from showing up as a running process because obviously I'm not interested in that one. May 2 '13 at 1:58
  • 2
    @acolyte it's not a surprise that you cannot see the "fnord" line. You are not supposed to be able to see it. If you have some 2 or 3 minutes to spare, search for it.
    – Francesco
    May 2 '13 at 9:54

16 Answers 16


Turns out there's a solution found in keychain.

$ ps aux | grep "[f]nord"

By putting the brackets around the letter and quotes around the string you search for the regex, which says, "Find the character 'f' followed by 'nord'."

But since you put the brackets in the pattern 'f' is now followed by ']', so grep won't show up in the results list. Neato!

  • 32
    @acolyte: The output from ps will include a line ending with grep [f]nord. However, that line will not make in through the grep filter, because the string [f]nord does not match the regular expression [f]nord.
    – LarsH
    Apr 30 '13 at 17:58
  • 10
    @LarsH interesting, thanks! i would have suggested ps aux | grep fnord | grep -v grep ...which seems to have already been suggested by a few people...lol
    – acolyte
    Apr 30 '13 at 18:16
  • 6
    @progo Yes, you do need to quote the [ even in bash. Try it with a file called fnord in the current directory. May 1 '13 at 22:18
  • 27
    Grepping the output of ps may be an old trick, but it's unreliable. Use pgrep if available. May 1 '13 at 22:19
  • 9
    @naxa Imagine you have a program call fnord and a program called safnorde. Or there's a user called bfnord, and you end up killing all his processes. Etc. Nov 24 '13 at 22:37

Another option I use (especially just to look if a process is running) is the pgrep command. This will search for a matching process, but not list a grep line for the search. I like it because it is a quick way of search, without regexing or escaping anything.

pgrep fnord

Moreover, to print both the process ID and the process name that is being matched, use (thanks phemmer)

pgrep -l fnord
  • 12
    They will want the -f option to be more like ps | grep.
    – jordanm
    Apr 30 '13 at 14:16
  • 1
    @jordanm Actually, pgrep -f will look more like ps -f | grep.
    – michelpm
    Apr 30 '13 at 18:09
  • 6
    There is also the -l argument to make it show the command that's being matched.
    – phemmer
    May 1 '13 at 3:34
  • 17
    ps | grep '[f]nord' is clever and venerable, but pgrep is right.
    – kojiro
    May 1 '13 at 11:33
  • 3
    You can always do ps $(pgrep cmd) ... if `pgrep is missing options (it won't work for empty set of commands though). May 1 '13 at 14:18

The ideal solution is the one presented by BriGuy

pgrep fnord 

But if you do not want to do that, you can just exclude all lines that matches with grep with:

ps aux | grep -v grep | grep "fnord"
  • 7
    but what if the line I'm looking for is "bash bash grep bash"?
    – Sparr
    Apr 30 '13 at 20:27
  • 1
    @Sparr Then you should use the best solution: pgrep or find another one ;)
    – RSFalcon7
    May 1 '13 at 15:15
  • Watch out for the name length limit with pgrep. Use -f to get the full path name or you might find your matches fail with longer names. -l is nice too to list the matches Dec 16 '14 at 14:32
  • Improved variation.
    – Murphy
    Oct 11 '19 at 8:04
  • According to man: -v, --inverse. Negates the matching. This option is usually used in pgrep's context.
    – Timo
    May 5 at 19:43

Not the most elegant solution but you could do this:

$ ps aux | grep fnord | grep -v grep

  • It's bad answer! Because if there was a word grep in your phrase. It will not show that process. For example, suppose a file called foo_grep_bar.txt is being edited by the nano command. So there's a process running: root 14908 0.0 0.0 110012 1692 pts / 3 S + Oct31 0:00 nano foo_grep_bar.txt According to this answer, this will not work: $ ps aux | grep nano | grep -v grep Because there's a grep word in your filename. Oct 31 '17 at 23:33
  • I prefer this as its more explicit about its intention than the accepted answer and works in all but one case.
    – samaspin
    Mar 28 '18 at 11:20
  • 1
    as per superuser.com/a/409658/450260 you should be excluding the full grep fnord not just grep i.e. $ ps aux | grep fnord | grep -v "grep fnord"
    – Davos
    Jul 26 '18 at 7:22
  • Improved variation.
    – Murphy
    Oct 11 '19 at 8:04
  • I like this answer best because people reading this don't have to wonder why in the world the grep requires brackets in the other case, it's not obvious at all unless you know why it's needed. This one is really clear. But both are great answers!
    – p e p
    Aug 16 at 15:41

In zsh, grep fnord =(ps aux).

The idea is, first run ps aux, put the result in a file, then use grep on that file. Only, we don't have a file, as we use zsh's "process substitution".

To illustrate, try

ps aux > ps.txt
grep fnord ps.txt
rm ps.txt

The result should be the same.

General comment on some of the other answers. Some are far to complicated and/or long to type. It is not only a matter of being right, it should be usable as well. But that doesn't mean some of those solutions are bad; only, they must be wrapped within a mini-UI to make them usable.

  • 1
    Not knowing zsh's process substitution, but is it certain that the two processes are called one after the other and not in parallel? May 1 '13 at 10:17
  • 3
    @PaŭloEbermann: For parallel is the <(command). grep grep =(ps aux) doesn't show any line. May 1 '13 at 14:17
  • Zsh can also ¨match¨ the output from ps.print -l ${(M)${(f)¨$(ps aux)¨}:#*fnord*}
    – Friartek
    Mar 9 '19 at 22:57

This answer is GNU-specific. See Wayne's answer for a more general solution.

Searching for processes

If you're just looking for fnord processes, you can use the -C option to select by command name:

ps -C fnord

This can be mixed with BSD- and POSIX-style format options to your liking. See the ps man page for a complete list.

Looking for someting else ?

If you need something more advanced than an exact search for a command name, don't loose hope! This can still be done on the ps side of the pipe. All we have to do is to tell ps to exclude grep processes from the result :

ps -NC grep | grep 'fnord'

-C grep selects all grep processes, and -N negates the selection. This can be used to search for command arguments, part of a command name, or more complex regular expressions.

  • 2
    This is good with GNU ps but -C is not specified by POSIX and has a a completely different meaning on BSD Aug 30 '16 at 18:02
  • It really is a bummer there's no BSD equivalent (which also means it won't work on a mac). Using ps -C is by far the simplest answer of any of these. Nov 9 '18 at 22:51
ps aux | grep $(echo fnord | sed "s/^\(.\)/[\1]/g")
  • 3
    this looks like an IOCCC, but for unix command line instead of C ^^ Just | grep $(echo fnord) wasn't enough ? you also ask sed to search and replace each char in "fnord" by its own value? ^^ congrats. I bet I can do an even longer one, but it probably won't be as funny ^^ Apr 30 '13 at 16:26
  • 1
    I apologize as the tone of my above comment may sound offensive (and I can't edit it after 5mn)... Your answer was really a joyful read, and I wasn't trying to make you look bad. I really think you did it like this on purpose ^^ Apr 30 '13 at 16:31
  • 1
    Don't apologize, your answer was really fun to read (and spot-on right too). I meant pgrep -l $1 anyway ;)
    – yPhil
    Apr 30 '13 at 16:48
  • 3
    @OlivierDulac: He doesn't just replace the first char with its own value; he replaces it with the concatenation of its value among square brackets. (Those square brackets are not special, they're literal.) Basically, he's generalizing on Wayne Werner's answer, so that the process of putting square brackets around the first character can be scripted. +1
    – LarsH
    Apr 30 '13 at 18:02
  • 2
    ps aux | grep '[^]]fnord' would avoid that gymnastic. Apr 30 '13 at 20:21

The simplest shell-agnostic way to do this would be to store it in a variable first:

PS_OUTPUT="$(ps aux)"; echo "$PS_OUTPUT" |grep fnord

Call-out: @EmanuelBerg's grep fnord =(ps aux) answer is by far the most elegant, though it requires zsh. I briefly had it in my rc files, but bash complains about that syntax even despite a conditional that should prevent its evaluation.

From my rc files, I have a case-insensitive version that takes grep's args:

psl() {
  local PS_OUTPUT="$(ps auxww)"
  echo "${PS_OUTPUT%%$'\n'*}" >&2  # title, in stderr to avoid pipes
  echo "${PS_OUTPUT#*$'\n'}" |grep -i "${@:-^}"

Code walk, one bullet per line of code:

  • Capture the verbose ps output (in a local variable so it goes away when the function returns)
  • Display the first line (the title) in standard error so the results can be further filtered without affecting the title. The substitution says: take $PS_OUTPUT and remove everything after the first line feed (regex equiv: s/\n.*$//msg). This prevents us from grepping the title
  • Display the ps output with everything except the first line (regex equiv: s/^.*\n//m) and grep its contents with -i for case-insensitive and with all of the arguments handed this function (in the case of no arguments, ^, which matches the start of any line to match everything)

My answer is a variation on the typical answer for searching for "foobar" in a 'ps' listing. The argument of "-A" "ps" is more portable than "aux", I believe, but this change is irrelevant to the answer. The typical answer looks like this:

$ ps -A -ww | grep [f]oobar

Instead I use this pattern:

$ ps -A -ww | grep [^]]foobar

The main advantage is that it's easier to write scripts based on this patterns because you simply concatenate a static string "[^]]" with whatever pattern you are looking for. You don't need to strip off the first letter of the string then insert it between the square braces and then concatenate the that back together again. When scripting in shell it's easier to simply stick "[^]]" in front of the pattern you were lookginfor looking for. String slicing in Bash is an ugly thing, so my variation avoids that. This variation says show the lines where the pattern matches WITHOUT a leading right-square-bracket ]. Since the search pattern to exclude a square bracket actually adds the square bracket to the pattern then it will never match itself.

So you could write a portable 'psgrep' command as follows. Here, I make some allowance for differences between Linux, OS X BSD, and others. This adds the column headers from 'ps', provides a more custom 'ps' format that suits my needs betters, and displays processes listing extra, extra wide so that none of the command-line arguments are missed. Well, most are not missed. Java being Java, it often does things in the worst possible way, so you some java services will run past the maximum allowed length of arguments that the process table will keep track of. I believe this is 1024 characters. The command-lone length allowed to start a process is much longer, but the kernel process table doesn't bother to keep track of anything over 1K in length. Once the command is started the command-name and argument list isn't needed against, so what gets stored in the process table is just informational.

psgrep ()
    case "$(uname -s)" in
            ps -A -ww -o pid,ppid,nice,pri,pcpu,pmem,etime,user,wchan,stat,command | grep -i -e "^[[:space:]]*PID" -e ${pattern}
            ps -A -ww -o pid,ppid,tid,nice,pri,pcpu,pmem,etime,user,wchan:20,stat,command | grep -i -e "^[[:space:]]*PID" -e ${pattern}
        *)  # other UNIX flavors get a minimalist version.
            ps -A -ww | grep -i -e ${pattern}

Here's an extended version of the grep -v grep solution, filtering out all grep processes that have not been running for more than a second, which is an improvement over "just discard all occurrences of grep".

$ ps -ef | grep -vw "00:00:00 grep" | grep <searchTerm>


$ ps aux | grep -vw "0:00 grep" | grep <searchTerm>

This may not be portable, and depends on the actual output format of your local ps command.

You may want to combine this with a coloured grep output for convenience:

$ alias grep='grep --color=auto'

Maybe time to use a real sequence this time. The use of pipes makes it parallel.

ps aux >f && grep tmpfs <f

Ugly because there will be a file f, but it's not my fault that there is no syntax for sequential processes where you still want to use the output of a previously run process.

Suggestion for the syntax of a sequential operator:

ps aux ||| grep tmpfs
  • The inability of the common people to easily filter a stream is hardly a reason for the elite to base themselves with sequences. It would be a step backward in computing.
    – Asclepius
    Aug 18 '14 at 20:27
  • @A-B-B en.wikipedia.org/wiki/Communicating_sequential_processes have many more operators than those that ended up in the Thompson shell. There could just have been an operator that is sequential, and which communicated its result to the next process in the sequence as soon as its exits. A "step backward in computing" by providing an additional operator seems a bit harsh. Aug 19 '14 at 7:09
  • Nice link, but of course sequential processing is worse in both CPU and memory (or disk) use -- relative to parallel processing. In this instance, if I must first store all ps output before I grep, I'm using more memory (or disk) for longer.
    – Asclepius
    Aug 19 '14 at 19:37

The pgrep command, as others have stated, will return the PID (process ID) of processes based on name and other attributes. For example,

pgrep -d, -u <username> <string>

will give you the PIDs, delimited by a comma (,) of all processes whose name matches being run by user <username>. You can use the -x switch before to return only exact matches.

If you want to get more information about these processes (as running the aux options from ps implies), you can use the -p option with ps, which matches based on PID. So, for example,

ps up $(pgrep -d, -u <username> <string>)

will give detailed information of all the PIDs matched by the pgrep command.

  • ps fails if pgrep returns an empty set. I have an answer which builds upon yours and tries to address this issue.
    – Asclepius
    Aug 19 '14 at 17:00

Here is a simple example to find PID of ssh-agent for username without showing PID of grep process itself:

ps xu | grep "${USER}.*[ ]/usr/bin/ssh-agent" | awk '{print $1 $2;}'

If you want for example to kill ssh-agent for current user you might use following command:

kill `ps xu | grep "${USER}.*[ ]/usr/bin/ssh-agent" | awk '{print $2;}'`

To create a handy alias add to your ~/.bashrc or ~/.zshrc file the following code:

function function1 () {
    ps xu | grep "$1.*$2" | awk '{print $1" "$2" "$11;}'
alias mygrep="function1"

And to use alias here are examples to force everyone to learn regular expressions:

. /etc/profile #to make alias usable
mygrep ${USER} ${PROCESS_PATH}
mygrep ${USER} "[f]nord"
mygrep "[f]nord"
mygrep ".*[s]shd"

P.S. I've only tested these commands on Ubuntu and Gentoo.

  • (1) The question doesn't say that the user is looking for one of his own processes — the user might not know the owner of the process he's looking for.  (2) As fancy as this answer is, it would still fail if you had said "${USER}.* /usr/bin/ssh-agent".  It works because you said [ ]; i.e., you are just using the mechanism of the accepted answer.  You might as well just grep "[s]sh-agent". Nov 6 '15 at 14:27
  • You are right. (1) I shared what might be useful as I found myself facing this page once in a while (2) Yes I used regular expression as in accepted answer. (3) I updated my answer to be the same as accepted as the one is better, but I also showed how to make and alias to be used with username provided or without it. (4) Also shown how to define function, though it is not necessary but works in interesting way as $1 and $2 doesn't overlap. Thx #G-Man Nov 7 '15 at 16:30

Using the -x (exact match) option worked for me. I combined it with -f (full command line), so I could match my process precisely with:

pgrep -x -f "path_i_used_when_starting/cmd params_i_used"
  • Will whoever is doing the drive-by downvoting explain themselves? This has been working to solve this issue for me without fail for years.
    – moodboom
    Apr 13 '19 at 18:37

Elaborating on @Emmanuel-Berg & @Adam-katz answers, you may use the POSIX option "-f $file" together with Bash's "Process Substitution" "<( $cmd)":

$ ps aux | grep -f <( echo fnord)

The pattern is passed to grep through a pseudo-file filled up by the command echo fnord. You may use this handy form which allows for several patterns (fnord + syslog), vs only one:

$ alias psgrep='ps aux | grep -f <( echo -e "$a")'
$ a="fnord\nsyslog"; psgrep

You can do it easily, just with defining an ALIAS in your .bashrc like this:

alias grep='grep -v grep | grep'
  • Not sure who down-voted or why but this allows you to use full use of ps that pgrep doesn't.
    – opticyclic
    Nov 27 '16 at 0:05
  • 1
    Not only that this inadvertently excludes other grep processes; it also breaks grep usage in other cases. Try echo I love grep | grep love.
    – trosos
    May 21 '17 at 22:54
  • @trosos Almost 11 years I've been *nix-ing .. and have never used that pattern ever ... maybe next year though - who knows right.
    – a20
    Mar 29 '18 at 11:08

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.