Super User is a question and answer site for computer enthusiasts and power users. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

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

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 – user127350 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. – user127350 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

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. – user127350 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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .