2

I have the code below and am receiving the following error output:

Enter your exam score
40
./if2.sh: line 6: 40: No such file or directory
Very well done. You have an A grade.

I'm using bash 4.1.2(1) on CentOS.

#!/bin/bash
#This script demonstrates the if-then-elif format.

echo "Enter your exam score"
read exam_pct
if [ $exam_pct < 40 ]
then
    echo "Sorry, you have failed."
elif [ $exam_pct > 70 ]
then 
    echo "Very well done. You have an A grade."
else
    echo "Well done. You passed."
fi

What's wrong here?

1
  • [ is a command. Shell scripts are much clearer if it is spelled correctly, and the correct spelling is test. When you write if test $exam_pct < 40 is is much more obvious that you are trying to invoke the command test $exam_pct with input redirected from the file 40. Commented Jun 18, 2013 at 2:43

4 Answers 4

4

if [ $exam_pct < 40 ] should be if [ "$exam_pct" -lt 40 ]

if [ $exam_pct > 70 ] should be if [ "$exam_pct" -gt 70 ]

Please always quote your variables.

Look at this for more details - http://tldp.org/LDP/abs/html/comparison-ops.html

Sign up to request clarification or add additional context in comments.

2 Comments

...you only need to quote your expansions in this case if you're using [ ]; [[ ]] and (( )) are syntax, preventing word-splitting and glob expansion regardless.
...by the way, the ABS is a pretty awful reference; much of its advice on that page (for instance, preferring (("$a" > "$b")) to (( a > b ))) is downright harmful. (Explicit expansions result in syntax errors in the case of null contents, whereas implicit ones in a math context don't).
4

Replace

if [ $exam_pct < 40 ]

with

if (( exam_pct < 40 ))

Take a look at the link given by Bill. Unix shell history is full of non-intuitive extensions. Depending on your case, Bash should be safe to use though. If you are interested in shell history take a look at http://www.in-ulm.de/~mascheck/bourne/

11 Comments

Is there any particular reason why I need [[ ]]? All the material I've read states [ ] unless that is only meant to be used on an older version of bash.
[[ ]] is a bash extension. It makes test condition a bit more versatile.
< is lexicographic in [[. If $exam_pct were 127, the condition would evaluate true. Use -lt and -gt just as with [, or use ((
But! you shouldn't pass user input to an arithmetic expression, because it might blow up with an arithmetic syntax error. (Try typing 40 foo or even 40foo to the question.)
@WilliamPursell Not portable to POSIX, granted, but [[ isn't strictly a bashism either; its usage here is identical in ksh or zsh as well. And, well, this is a question tagged bash.
|
3

To elaborate on why you're getting the error you're getting: [ isn't special syntax; it's just an executable (usually provided through a builtin, though /usr/bin/[ probably exists on your system), which by convention takes "]" as its last argument.

So when you write [ $exam_pct < 40 ], what you're actually doing is starting [ with (ideally) two arguments (the contents of $exam_pct, and ]), and the contents of a file with the name 40 piped to its stdin.

Similarly, when you do [ $exam_pct > 70 ], you're redirecting the output of [ $exam_pct ] (which will be blank, because [ doesn't ever write to stdout) to a file called 70.

Comments

1

Just for completeness:

if [ $exam_pct \< 40 ]

also works

3 Comments

It isn't in pubs.opengroup.org/onlinepubs/007904875/utilities/test.html, and so only works by way of a nonstandard extension. Isn't the only point to using [ or test to be standards-compliant?
I don't think it's a non-standard extension, but rather a way to protect the < from being interpreted as a redirection operator and performing string comparison instead. For integer comparison, $exam_pct -lt 40 is required. Using string comparision, [ 100 \< 40 ] would be true, because the comparison is lexicographic, not arithmetic.
But... but... OP needs integer comparison, not string comparison.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.