Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

Here is my script, I get the error "line 33: [: too many arguments", I'm confused why, surely only 2 arguments are being provided to cp here?

I am providing two directories to the script with no spaces in them, i.e. $1=dir1/ and $2=dir2/

#!/bin/bash

### Assign suitable names to arguements. ###

source=$1
dest=$2

### Error handler for all script errors. ###

function errorHandler {
    case $1 in
        ERRargs) printf "USAGE: e2backup source_dir dest_dir.\n"; exit 1;;
        ERRsource) printf "ERROR: Source does not exist or is not a directory.\n"; exit 2;;
        ERRdest) printf "ERROR: Destination does not exist or is not a directory.\n"; exit 3;;
        ERRempty) printf "ERROR: Destination is not empty.\n"; exit 4;;
    esac
}

### Test num. of args, source/dest validity and empty dest. Then perform backup. ###

if [ $# -ne 2 ]
  then
    errorHandler ERRargs
elif [ ! -d $source ]
  then
    errorHandler ERRsource
elif [ ! -d $dest ]
  then
    errorHandler ERRdest
elif [ -n "$(ls -A $dest)" ] 
  then
    errorHandler ERRempty
elif [ cp -R $source $dest ]
  then
    printf "Successfully backed-up from $source to $dest"; exit
else
    printf "Back-up failed, please see e2backup.error"; exit 5
fi
share|improve this question
add comment

2 Answers

It is not cp but [ aka test which gives you the error

share|improve this answer
    
And how can I mitigate this issue? I want to use the return status for the elif but carry out the cp at the same time... –  Mike Mar 7 '13 at 22:35
2  
Let's say you want to keep this kind of bad coding (in my opinion) ... You need to have as output the return code: elif $(cp -R "$source" "$destination"; printf "%d" "$?"); then –  Radoo Mar 7 '13 at 22:45
2  
elif tests the return status of the following command. Usually the command it [, an alias for test. If you want to branch on the return status of cp, simply write elif cp -R $source $dest. –  garyjohn Mar 7 '13 at 23:59
    
+1 Gary, his version is correct too. I thought it my way, where I always separate commands and exit codes from tests. –  Radoo Mar 8 '13 at 7:01
    
Nice one chaps. And why is this bad coding in your opinion? Any tips would be appreciated. –  Mike Mar 8 '13 at 14:06
show 4 more comments

To the point, the statement cp -R $source $dest is not a test condition in itself. So you should tell BASH to execute the cp commands. You can either use the back-quote or $(...) and test against the result or better as suggested by one commenter:

if [[ $# -ne 2 ]]
  then
    errorHandler ERRargs
elif [[ ! -d $source ]]
  then
    errorHandler ERRsource
elif [[ ! -d $dest ]]
  then
    errorHandler ERRdest
elif [[ -n "$(ls -A $dest)" ]]
  then
    errorHandler ERRempty
elif cp -R $source $dest
  then
    printf "Successfully backed-up from $source to $dest"; exit
else
    printf "Back-up failed, please see e2backup.error"; exit 5
fi

Updated: BASH supports both '[]' and '[[]]' for a test. There is a slightly different meaning that the curious one can find in the man page. In addition, one could also use other ways to do a test, like using the test bash builtin command.

share|improve this answer
    
Your recall is wrong. [] is equivalent with test. [[]] is a new compound introduced in bash since some version I don't recall, which extends test functionality with pattern matching. Even tough it's a very useful feature, this compound is not POSIX, which, in some cases, might not be desirable, like when you want your script to be distributed across diferent shells. –  Radoo Mar 9 '13 at 19:21
    
At Radoo, thanks I will correct the answer. However, as this is a bash scrip (first line is #!/bin/bash) the '[[]]' will work on any platform which supports Bash. Even when trying to make a script as much agnostic to a specific shell, I never managed to have it portable without modification from let says BASH to KSH. –  Huygens Mar 10 '13 at 13:23
    
There's no reason to capture the standard output of cp, since it generally doesn't produce any. Just us elif cp -R "$source" "$dest" to test the exit status of cp. –  chepner Mar 11 '13 at 15:17
    
@chepner I am not sure what I ate that day, must have been pretty bad ;-) I corrected it once more and even made this post a community wiki as my original answer is quite far from what the current is thanks to both Radoo and you! –  Huygens Mar 11 '13 at 15:30
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.