Why "if $(ps aux | grep ...)" always succeeds in Bash?
Asked Answered
G

5

23

Why the following if statement succeeds ?

if $(ps aux | grep -q "bla bla") ; then echo "found" ; fi
Genova answered 22/1, 2012 at 23:1 Comment(3)
If your run ps aux | grep "bla bla" you will see why...Simba
See also this question.Polonaise
if pgrep -f "bla bla"; then echo "found"; fiWinou
S
43

Because the grep process itself is being returned by ps. You can "trick" grep to not match itself by surrounding one of the search characters in a character class [ ] which doesn't change the functionality: Just do:

if ps aux | grep -q "[b]la bla" ; then echo "found" ; fi

Also, the use of process substitution $() is unnecessary. The if will work on the success of the last command in the pipe chain, which is what you want.

Note: The reason the character class trick works is because the ps output still has the character class brackets but when grep is processing the search string, it uses the brackets as syntax rather than a fixed string to match.

Sweetsop answered 22/1, 2012 at 23:4 Comment(1)
I got entirely too excited about this trick. :D Piping to | grep -v grep always made me sad and now I don't have to do that anymore!Swashbuckling
A
10

If you grep the output from ps aux, you will always get a process showing your previous command. To fix this, you can pipe the output to grep twice, once to remove line with "grep" in it, and again for the process your looking for.

ps aux | grep -v "grep" | grep "Finder"
Aboutface answered 22/1, 2012 at 23:26 Comment(0)
F
9

the 'grep' process is already running by the time ps runs, so the ps output includes it.

Try using pgrep instead.

pgrep is precisely for this purpose:

if pgrep "bla bla" ; then echo "found" ; fi

Forced answered 22/1, 2012 at 23:6 Comment(1)
Mr Downvoter, I have edited my answer for better clarity. Please see if it looks better now. TaForced
W
2

The $( is a small little bit relevant, and changes the meaning a bit. Although in this case, because there is never any output from grep -q, you can just about get away with the $(. You probably want to start with something like (as pointed out by others):

if ps aux | grep -v 'grep' | grep -q 'bla bla'; then
    echo 'Found'
fi

Anyway, you started with

if $(ps aux | grep -q "bla bla") ; then echo "found" ; fi

With $(, the command inside the $( ) is executed and the output of that command is used as the command line for the outer command. Do these four experiments:

# if $(echo nonexistant ; true) ; then echo "found" ; fi
nonexistant: command not found

# if $(echo nonexistant ; false) ; then echo "found" ; fi
nonexistant: command not found

# if $(echo  ; true) ; then echo "found" ; fi
found

# if $(echo  ; false) ; then echo "found" ; fi

So, according to this you will output get found if both these conditions hold:

  • The command inside the $( ) created no output
  • and the command was succesful

This suggests that ps aux | grep -q "bla bla" was successful and created no output. It's no surprise that grep -q creates no output. That's what the -q is for. So therefore, your command must have had a true status, which implies that the grep did successfully find a match. We know that grep will always find a match in this case, because the list of processes from ps will include grep itself; the grep will always find itself.

Woodpecker answered 22/1, 2012 at 23:30 Comment(1)
nice 'exploded' explanation of what is happening.Maddy
O
1

You need to filter out the process that is grepping for 'bla bla':

$ if ps aux | grep -v 'grep' | grep -q 'bla bla'; then
    echo 'Found'
fi
Odious answered 22/1, 2012 at 23:10 Comment(4)
don't you want the -v grep after the target grep? (If I downvote, I say why).Maddy
I also got downvoted twice with no explanation. I think someone is downvoting very liberally on this question ...Forced
@amir75 : looks liked all the downvotes have disappeared (again with no explanation!) ;-) Good luck to all.Maddy
@shellter: Normally, yes, I would filter after the grep, but since we're calling grep -q, there's nothing to filter. I don't follow the downvote comments (there are no votes on this answer).Odious

© 2022 - 2024 — McMap. All rights reserved.