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'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."
else

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?

share|improve this question
    
Try using double-quotes instead. I think the shell is not expanding the $2 parameter right with single quotes. –  Herman Torjussen Jan 6 '12 at 15:12

3 Answers 3

up vote 7 down vote accepted

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
fi

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

share|improve this answer
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 '12 at 15:17
    
Check out Gilles' answer for much more detailed explanations. –  jw013 Jan 8 '12 at 19:44
grep -q -e "^$2:" /etc/group

should work.

(single quotes prevent interpolation)

share|improve this answer

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";;
esac
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.)

share|improve this answer

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.