Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I am using bash. I have a file named "a2draw" that contains only 1 line:

sleep 99999

I start it using this command:

bash a2draw &

Now, I know and understand the trick with square bracket that allows you to omit grep process in ps output:

ps aux | grep cron
root      1079  0.0  0.0   2596   788 ?        Ss   Mar25   0:00 cron
root      1119  0.0  0.0   3684   696 ?        Ss   Mar25   0:00 /usr/sbin/incrond -f /etc/incron.conf
ja       29781  0.0  0.0   4368   820 pts/10   S+   12:49   0:00 grep cron

ps aux | grep [c]ron
root      1079  0.0  0.0   2596   788 ?        Ss   Mar25   0:00 cron
root      1119  0.0  0.0   3684   696 ?        Ss   Mar25   0:00 /usr/sbin/incrond -f /etc/incron.conf

But it somehow doesn't work in the subshell that has jobs running in the background:

jobs
[1]+  Running                 bash a2draw &

ps aux | grep [a]2draw
ja       22977  0.0  0.0   5172  1080 pts/10   S    12:21   0:00 bash a2draw
ja       30242  0.0  0.0   4364   816 pts/10   R+   12:50   0:00 grep

What is even more strange, dropping one letter from the process name yields correct results:

ps aux | grep [a]2dra
ja       22977  0.0  0.0   5172  1080 pts/10   S    12:21   0:00 bash a2draw

On another shell everything works as I expected:

ps aux | grep [a]2draw
ja       22977  0.0  0.0   5172  1080 pts/10   S    12:21   0:00 bash a2draw

ps aux | grep [a]2dra
ja       22977  0.0  0.0   5172  1080 pts/10   S    12:21   0:00 bash a2draw

I don't know what's going on. Is there something special about background jobs that modify how creation of pipe works?

share|improve this question
1  
try adding quotes around your grep pattern: ps aux | grep "[a]2draw" –  SuperMagic Mar 27 '13 at 12:28
    
Yes, forgot to mention that this also helps helps to omit grep in ps output in subshell when a2draw is running. But why? –  user1042840 Mar 27 '13 at 12:37
    
"What is even more strange, dropping one letter from the process name yields correct results" That's not strange at all. That's how grep is suppose to work (it finds patterns, which are not necessarily whole words). Try ps aux | grep --color=always "[a|e|i|o|u]" and see what happens. –  goldilocks Mar 27 '13 at 13:04
    
SuperMagic nails it, I think : [a] will be replaced at invocation time by the shell, so grep receives "a2draw", but "[a]" will be passed to the grep, which will receive "[a]2draw" and correctly fail to see its own line (as [a]2draw matched .*a2draw.* but not .*[a]2draw.*) –  Olivier Dulac Mar 27 '13 at 13:16
    
the fact that sometimes you don't see grep doesn't come from dropping a letter : it comes that you don"t always have ps showing the "grep" line AFTER grep started : sometimes it ps before grep starts, so you don"t see the grep line in the ps output. Try : while [ 1 ] ; do ps aux | grep a2draw | wc -l ; done : it should sometimes show 1, sometimes 2 (depending on the output of ps, depending on the order the shell started both sides of its pipe) –  Olivier Dulac Mar 27 '13 at 13:17

1 Answer 1

up vote 2 down vote accepted

Had you used zsh or (t)csh instead of bash, you'd have understood your mistake:

$ ps -ef | grep [c]ron
zsh: no matches found: [c]ron

Above, you've got a globbing pattern that is meant to expand to the list of files in the current directory matching that pattern.

In most Bourne-like and rc-like shells however, if there's no matching file, the pattern is silently passed untouched to the command.

That is why it works with [c]ron, because there's no file called cron in the current directory, but not with [a]2draw, because there is one file matching that pattern in the current directory, it is expanded by the shell to a2draw and grep gets a a2draw argument instead of [a]2draw.

Note that bash can be configured to work like zsh in this case by doing:

shopt -s failglob

The fish shell also reports an error when a glob does not match. However [...] is not a globbing operator in fish.

What that means is that you need to quote globbing characters when you don't intend them to be expanded:

ps -ef | grep '[a]2draw'

You can get away without doing that in bash or other Bourne-like shells except zsh, but that makes for dormant bugs ready to kick in the day you run the command in a directory that has a matching file.

I can have nasty side effects like in unsuspected contexts. Like:

rm -?

In a directory that has files called --, -x and -y would remove both -x and -y.

share|improve this answer
    
Oh damn, that was so simple. I learn every day. I consider switching to zsh right now, it seems to have many enhancements over bash, some guy here is using it too. –  user1042840 Mar 27 '13 at 13:18

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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