I spent yesterday writing (Bash) shell scripts like some kind of machine. I came upon this problem:
function create {
$HTPASSWD $USERFILE $user $pass
if [ ! `grep -q " $user " $GROUPFILE` ]; then
echo "Adding user to group $GROUP ..."
sed "s/$GROUP\:/$GROUP\: $user/" $GROUPFILE > $GROUPFILE.tmp
cp $GROUPFILE.tmp $GROUPFILE
else
echo "User is already in group $GROUP"
fi
}
What this should do is add a string to a file if the string is not already in the file. Simple enough but the logic in the ‘if’ is always evaluating to true. If I run the same grep on the command-line and check the return value I get the desired result:
cliph@clflood-desktop:~/bin$ grep -q hello xtranetgroups; echo $?
0
cliph@clflood-desktop:~/bin$ grep -q antihello xtranetgroups; echo $?
1
So then I tried this small piece of code to test command substitution and return codes in if statements (being in a function doesn’t seem to cause a problem):
if [ `ls ./$file` ]; then
echo "True"
else
echo "False"
fi
It works perfectly:
cliph@clflood-desktop:~/bin$ ./true file
True
cliph@clflood-desktop:~/bin$ ./true filenothere
ls: ./filenothere: No such file or directory
False
So that leaves me stumped, why does my grep not work in the first example?
Is it because $user evaluates to an empty string?
$user always has a value, the “create” function wont be reached if $user is null
In the script, you’re doing this:
grep -q \” $user \” $GROUPFILE
On the command line, you’re grepping just for the user. Do you mean to grep for $user with a space on either side? That’s what you’re doing in the script.
Yes, thats what I want to do in case there’s a new user that has a name similar to an old one. grep’s ‘-w’ flag has been pointed out to me and should work just as well as whitespace padding but I’m getting the same result.
On the other hand, I don’t think that grep will actually return a 1 or 0 in your script. backticks return the output from a statement, not the return value. So, you’re NOTing nothing (i.e. 0) which evaluates to true.
Do the grep in a statement before your if, then use the if to test the value of $?
grep -w $user $GROUPFILE
if [ ! $? == “1″]
etc
if grep -vq ” $user ” $GROUPFILE
then
… seems to work for me (ubuntu hoary).
DoC wins for the first working solution and an explaination.
Learning is fun.
Surely I should get some points for elegance and lack of disruption to your original script? :(
I tried yours and it didn’t work, for me at least. Good effort though.
Thanks to everyone who replied.
I win! \o/