I'm writing a bash script wherein I want to check that one of the arguments passed to it is a valid group.

I have the line

if [ `grep -c -e '\b$2\b' /etc/group` -eq 0 ]; then
  echo "Error: $2 is not a valid group."

Which always tells me that valid groups aren't valid.

I think it's an escaping problem; I think it's grepping for a group called $2. The error message properly shows the passed argument. However I'm not sure if I'm escaping $2 within the backticks properly.

How do I get this line working?

  • Try using double-quotes instead. I think the shell is not expanding the $2 parameter right with single quotes.
    – user13742
    Jan 6, 2012 at 15:12

3 Answers 3


Using grep's -q option is much more efficient than command substitution.

if ! grep -q -e "^$2:" /etc/group; then
    echo "Error: $2 not a valid group" >&2

The issue is single quotes (') prevent shell variable expansion ($). You need to use double quotes (").

  • 1
    +1, beat me by 10 seconds. In short, grep will return 0 (success) if it finds a match, so there's no reason to count the matches.
    – l0b0
    Jan 6, 2012 at 15:17
  • Check out Gilles' answer for much more detailed explanations.
    – jw013
    Jan 8, 2012 at 19:44
grep -q -e "^$2:" /etc/group

should work.

(single quotes prevent interpolation)


You're passing \b$2\b to grep literally because of the single quotes. To allow $2 to expand to the value of the argument, use "$2". Also, quoting between backquotes can get tricky; use $(…), which has the same meaning as `…` (command substitution) but behaves sanely with regards to quoting.

if [ $(grep -c -e "\b$2\b" /etc/group) -eq 0 ]; then …

Next, counting the matches is overly complicated: you can use grep's return status to know whether there were matches. Pass the -q option to tell grep that you aren't interested in any output, just the return status.

if ! grep -q -e "\b$2\b" /etc/group; then …

Next, your search is wrong. You're looking for the word $2, but that could match a user name, or a part of a group name that contains a punctuation character, or a few more exotic mismatches. The group name is the first colon-delimited field, so search for that.

if ! grep -q -e "^$2:" /etc/group; then …

Note that you may need to sanitize the input: $2 must not contain any character that's special to grep or that's a group delimiter.

case $2 in
  *[][\.*^$]*) echo "Unsupported character in the group name";;
if ! grep -q -e "^$2:" /etc/group; then …

Finally, grep /etc/group is not the right tool here, if you can avoid it. You can only find local group names that way, not groups coming from NIS or LDAP or unusual setups. Most modern unices (at least Solaris, Linux and *BSD) have a getent command to retrieve entries from system databases including the group database.

if ! getent group "$2" >/dev/null; then …

(For users, instead of looking in /etc/passwd, use getent passwd, or more portably call id.)

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .