I have been using the below code ok for some time, but now I get an error

java Editor < "input/editor$i.in" > "tmp/editor$i.out"
diffCurr="$(diff "tmp/editor$i.out" "output/editor$i.out")"
if [ -n $diffCurr ]

Error (occurs on last line of above snippet):

[: too many arguments

What's wrong? I am trying to test that the diff result was empty (ie. same contents in file)


There's no need to put the output of diff in a variable, since you can tell whether files differ based on the exit status of diff, e.g.

if diff -q file1 file2 >/dev/null 2>&1; then
        # files are equal
        # files differ, or an error occurred

diff returns success (0) if the files do not differ. Adjust the logic as necessary.

Testing exit statuses of commands when possible is almost always preferred over checking or parsing output via command substitution.

For the sake of completeness, the error with your original example happened because you didn't quote "$diffCurr" in the if line, so it went through "word splitting" into more than one word --- hence "too many arguments".

  • what does 2>&1 do? – Jiew Meng Oct 9 '11 at 10:31
  • The redirections on the end (>/dev/null 2>&1) serve to hide the output of diff. 2>&1 redirects stderr to the same place as stdout, which was earlier in the same line sent to /dev/null (a virtual black hole). – jw013 Oct 9 '11 at 10:35
  • Sorry, I still dont really get it. I understand the 1st part diff -q file1 file2 > /dev/null as having output redirected to /dev/null. But does 2 mean any errors from diff to /dev/null (represented by &1 in this case?) too? – Jiew Meng Oct 9 '11 at 13:49
  • 3
    If you are only interested in the output you can replace diff with cmp ... – maxschlepzig Oct 9 '11 at 16:59
  • 1
    @jiewmeng That's the "copy descriptor" operator. There's some good information about it here. – Chris Down Dec 19 '11 at 15:55

jw013 is right, you don't need this line anyway.

But to answer the actual question, you have left out quotation marks around the variable that you passed into test (otherwise known as [).

This means if your variable is empty, it will be as if you had no arguments (eg [ -n ]), and if your variable contains spaces, it will be as if you passed multiple arguments (I'm guessing this is what happened).

Always wrap the strings under test with quotes, eg:

if [ -n "$myvar" ]
  • "This line" may be needed if the output is to be sent somewhere, say through mail or to dialog. – Arcege Oct 9 '11 at 14:44

It may be better to test the exit code of the diff command than the output.

diffCurr="$(diff "tmp/editor$i.out" "output/editor$i.out")"
if [ $? -ne 0 ]; then  # different

If you are not interested in the output, then you can do as jw013 suggests.


In addition to the good answers above: My love/hate relationship with bash is focused primarily around its strength in parameter substitution and in the fact that getting it to stop substituting when you want it to can be quite challenging - especially when a variable gets used or altered more than once.

As a result, I almost always code variable references like:


This makes sure B gets treated as a single string (most often what I want) and it allows things like


to work as well as a bunch of other fancy options that only work inside the braces.

If I code even a simple safe variable reference as


to start with, I'm a lot safer when I go back in to modify the code later and possibly do something that might fail if the quotes or braces were missing.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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