0

First: I'm fairly new to bash batch-scripting but have experience in other script and programming languages

Second: I already looked at Meaning of "[: too many arguments" error from if[] (square brackets) but this that was not the solution for my problem.

I'm creating a command-line parser in a bash script. My first attempt actually already works but still has some if-statement code-duplication in the main-loop which I want to solve, so I moved it to the actual parsing-function and then I run into a "[: too many arguments" error which I cannot get solved (adding "" around variables did not work) in a piece of code which does work if I do not move the if.

Note: in the actual code there is one more command-line option, I left that out for 2 reasons:

  1. shorter listing
  2. error is seen on all options

The working code looks like this:

    arg_str = $@
    args=("$@")
    arglen=$#

    target=some_filename.txt
    in_dir=/some_input_dir/

    function working_parser()
    {
        local option=$1
        myresult=''

        i=0

        while [ ${args[i]} != $option -a $i -n $arglen ]
        do
            i=$((i+1))
        done
        #TODO add check on $i>arglen
        myresult=${args[$((i+1))]}
    }

    if [[ $arg_str == *'-t'* ]]; then
        working_function '-t'
    fi
    if [[ $myresult != '' ]]; then
        target=$myresult
    fi


    if [[ $arg_str == *'-i'* ]]; then
        working_function '-i'
    fi
    if [[ $myresult != '' ]]; then
        in_dir=$myresult
    fi

The failing code looks like this (Left out the definitions, since they are the same as for the working code). The '[: too many arguments' error occurs in the while loop, where it did not happen in that same code in the working-version.

    function failing_parser()
    {
        local option=$1
        myresult=''

        if [[ $arg_str == *$option* ]]; then
            i=0

            while [ ${args[i]} != $option -a $i -n $arglen ]
            do
                i=$((i+1))
            done
            #TODO add check on $i>arglen
            myresult=${args[$((i+1))]}
        fi
    }

    failing_parser '-t'
    if [[ $myresult != '' ]]; then
        target=$myresult
    fi

    failing_parser '-i'   
    if [[ $myresult != '' ]]; then
        in_dir=$myresult
    fi

What am I doing wrong?

7
  • 1
    Quotes! while [ "${args[i]}" != "$option" -a "$i" -n "$arglen" ] Commented Aug 28, 2019 at 9:54
  • I tried quotes and it does not work. Still keep getting the same issue. (Actually used the same line as Kamil suggests) /*edit*/ now even tried it with quotes around the variables in both the if and while loop Commented Aug 28, 2019 at 10:06
  • -n is unary, not a binary, operator; "$i" -n "$arglen" is an invalid expression. What are you actually trying to do? Note also that -a for logical AND is considered obsolete; use [ ... ] && [ ... ] instead, or use [[ ... && ... ]]. Commented Aug 28, 2019 at 12:56
  • Did you mean -ne instead of -n? Commented Aug 28, 2019 at 12:56
  • @Nemelis, if quoting doesn't fix your whole problem, that's still not a reason not to quote. The code is even more broken without quoting than it is with quoting, insofar as without quoting you have additional bugs that show up when your values don't string-split and glob to the expected number of words (presumably one per expansion, but unless you quote that isn't a guarantee). Commented Aug 28, 2019 at 13:03

1 Answer 1

2

There are too many arguments because -n is unary operator, not a binary operator. Perhaps you mean -ne?

while [ "${args[i]}" != "$option" -a "$i" -ne "$arglen" ]

-a is considered nonportable and obsolete; it's better to use two separate [ commands joined by && instead:

while [ "${args[i]}" != "$option" ] && [ "$i" -ne "$arglen" ]

However, since you are already using one bash-specific feature (arrays), you may as well use [[ ... ]] as well:

while [[ "${args[i]}" != "$option" && "$i" -ne "$arglen" ]]

or even an arithmetic command:

while [[ "${args[i]}" != "$option" ]] && (( i != arglen )); 
Sign up to request clarification or add additional context in comments.

2 Comments

First saw your comment above and already reacted over there. Thank you for your help.
After I wrote the comment, I realized the assumption was probably safe enough to go ahead with an answer :)

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.