3

So below is the code i have in my bash script. I'm getting an error saying binary operator expected when i give the command 2 arguments (doesnt give error when i give 1 argument). It does change the file permissions when i give 2 arguments because i can see it when i do ls -l but it still gives me this error. How do i fix it?

for file in $@
do
    chmod 755 $file
done

if [ -z $@ ]
then
        echo "Error. No argument."
        exit $ERROR_CODE_1
fi

i have added this now

if [ ! -f "$*" ]
then
       echo "Error. File does not exist"
       exit $ERROR_NO_FILE
fi

But now when i enter more than 1 argument it just does everything in the if statement (i.e. prints error.file does not exist) even when the file does exist.

pogba123
  • 79
  • 1
  • 3
  • 9
  • Don't change your question. If you have a *new* question you should post it as a new, instead of changing your *existing* question. – Andreas Louv Dec 02 '16 at 19:56

3 Answers3

5

Doing it another way: just ask how many parameters were passed:

...
if [ $# -eq 0 ]
...

You get the error in your code because the $@ variable expands to multiple words, which leaves the test command looking like this:

[ -z parm1 parm2 parm3 ... ]

Jeff Schaller
  • 2,352
  • 5
  • 23
  • 38
3

$@ is expanding to all the arguments, with spaces between them, so it looks like:

if [ -z file1 file2 file3 ]

but -z expects just one word after it. You need to use $* and quote it, so it expands into a single word:

if [ -z "$*" ]

This expands into:

if [ -z "file1 file2 file3" ]

Or just check the number of arguments:

if [ $# -eq 0 ]

You should also put this check before the for loop. And you should quote the argument in the for loop, so you don't have problems with filenames that have spaces:

for file in "$@"
Barmar
  • 741,623
  • 53
  • 500
  • 612
  • i have updated my code above in the question box and am getting a different error please can you help me. i am a beginner and need help. – pogba123 Dec 02 '16 at 19:33
  • `-f` expects just a single filename after it, but you're combining all the filename arguments into a single test. – Barmar Dec 02 '16 at 19:34
  • If you have a different question, you should post a new question, not add it to a question that has already been answered. – Barmar Dec 02 '16 at 19:35
  • Yes so how do i fix it. Please. For loop i guess. – pogba123 Dec 02 '16 at 19:38
  • I don't understand what you want to do. You should use `if [ ! -f "$file" ]` inside the `for` loop. Why would you test the entire argument list? – Barmar Dec 02 '16 at 19:39
1

Wrap your parameters in double quotes to avoid word splitting and pathname expansion:

for file in "$@"
do
    chmod 755 "$file"
done

if [ -z "$*" ] # Use $* instead of $@ as "$@" expands to multiply words.
then
        echo "Error. No argument."
        exit "$ERROR_CODE_1"
fi

You can however change the code a little:

for file # No need for in "$@" as it's the default
do
    chmod 755 "$file"
done

if [ "$#" -eq 0 ] # $# Contains numbers of arguments passed
then
    >&2 printf 'Error. No argument.\n'
    exit "$ERROR_CODE_1" # What is this?
fi
Andreas Louv
  • 46,145
  • 13
  • 104
  • 123
  • i have updated my code above in the question box and am getting a different error please can you help me. i am a beginner and need help. – pogba123 Dec 02 '16 at 19:32