简体   繁体   中英

Bash: command not found

Bash shell, the following code snippet results in the error: "too many arguments". I have searched thoroughly and cannot get to the bottom of this.

if [ [ $i % 3 ] == 0 ] && [ [ $i % 5 == 0 ] ]

I am just learning bash, any help is much appreciated, thanks in advance!

Solved: if [[ $((i % 3)) == 0 && $((i % 5)) == 0 ]] thank you @BroSlow

You can simplify this by using an arithmetic expression:

if (( i % 3 == 0 && i % 5 == 0 )); then

(or even more simply, with (( i % 15 == 0 )) ...).

Let me explain this a little more: in bash there are four main types of conditions you'll see in an if command:

  1. [ ... ] -- the [ and ] look like a some kind of parentheses, but [ is actually a synonym for the test command, and evaluates its arguments as a conditional expression. It does not understand additional [ ] pairs as parentheses, you have to use ( ) instead. But because it's a command, all of its arguments are subject to the usual shell parsing before being handed to the command, and so you'd have to escape them like \\( ... \\) , which is annoying. And you can't use && because that separates commands, you have to use -a instead.

    And there are a pile of other parsing oddities, like if you use < or > you have to escape them or it'll treat them as input/output redirects. Seriously, if you use if [ 3 > 5 ] , it'll create a file named "5", and dump the output of the command [ 3 ] into it. And BTW [ 3 ] doesn't output anything, but it does return success (ie true) because "3" is not blank...

    Basically, you should not use [ ... ] unless you need compatibility with generic shells that don't support any of the better options.

  2. [[ ... ]] -- this is a bash conditional expression, which is basically a cleaned up version of [ ... ] (aka test ), with the weird parsing oddities removed and some cool additional features added. You can use parentheses (not brackets) for grouping, and < and > for comparison, all without escapes. If you're using bash (not a generic shell), this is usually the way to go. But it doesn't do math (it's all string-oriented), unless you force arithmetic evaluation of something with $(( )) (as in BroSlow's answer).

    And a warning: in [[ ... ]] , = , != , < , and > do string comparisons, not arithmetic. For example, [[ 05 = 5 ]] is false, because they aren't textually equal. And [[ 10 > 5 ]] is also false, because "1" comes before "5" alphabetically (well, in standard sorting order). If you want arithmetic comparisons here, you need to use -eq , -ne , -lt , and -gt instead.

  3. (( ... )) -- this is an arithmetic expression. Sort of similar to [[ ]] , except the contents get evaluated as a mathematical expression instead of string-oriented tests. Note that in a math context, variables get evaluated automatically, so you can use i instead of $i . Also, = is an assignment, while == is a comparison (in [[ ... ]] , they're both comparisons).

    This is confusingly similar to the $(( ... )) thing I mentioned in the last item. The difference is that (( ... )) acts like an entire command on its own, while $(( ... )) evaluates the contents and returns the result for inclusion in some other command . For example, echo $((3+5)) will evaluate to echo 8 , which then prints "8".

  4. Some other command. You can use any command you want as the test in an if statement, and if will execute the then or else branch based on whether the command succeeds or fails. You'll see things like if grep somepattern somefile; then... if grep somepattern somefile; then... and if somecommand; then echo "it worked"; else echo "it failed"; fi if somecommand; then echo "it worked"; else echo "it failed"; fi if somecommand; then echo "it worked"; else echo "it failed"; fi , and such. All of the other three options are really just special cases of this: you can use [ ...] , [[ ... ]] , or (( ... )) anyplace you'd use any other command in bash, they just happen to be particularly useful as if conditions.

You can't nest brackets inside of brackets in bash. So [[ ]] is fine [ ] is fine but [ [ ] ] is not (it assumes the nested brackets are operators). And if you want some math you can do $((math))

Should be

if [[ $((i % 3)) == 0 && $((i % 5)) == 0 ]] 

Also see

Too many arguments error in bash

you cannot have space between [ and next [ . Change [ [ to [[ . Same with ] ] .

See Conditional expressions in bash.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM