Take the 2-minute tour ×
Ask Ubuntu is a question and answer site for Ubuntu users and developers. It's 100% free, no registration required.

I want to test if there is any output from the diff (test if files are same), if none echo "Passed $x" else echo "Failed $x". I came up with some intermidiate step (save the output from diff to a file then read from file)

diff "./helloworld$x.out" "./output/helloworld$x.out" > tmp.txt;
output="`cat tmp.txt`";

if [ "$output" = "" ];
  then
    echo "Passed $x";
  else
    echo "Failed $x";
  fi;

I'm sure the code can be improved? Main question is: is it possible to save the output from diff directly into a variable?

share|improve this question

4 Answers 4

up vote 16 down vote accepted

This works:

if diff "./helloworld$x.out" "./output/helloworld$x.out" >/dev/null; then
    echo "Passed $x";
else
    echo "Failed $x";
fi

If you use a variable instead of echo you could drop the else branche: set the variable to false before the if and save 2 lines of code.

If you want to actually put the result into a variable use:

some_var="$(diff "./helloworld$x.out" "./output/helloworld$x.out")"

Including my test to see if it does actually work:

rinzwind@discworld:~$ touch 1
rinzwind@discworld:~$ touch 2
rinzwind@discworld:~$ more test
if diff 1 2 >/dev/null; then
    echo "Passed $x";
else
    echo "Failed $x";
fi
rinzwind@discworld:~$ ./test
Passed 

rinzwind@discworld:~$ vi 2
rinzwind@discworld:~$ more 2
2
rinzwind@discworld:~$ ./test
Failed 

On the >/dev/null part: >/dev/null 2>&1 will send output to >/dev/null and 2>&1 will send standard errors to the same file (&1 means 'use first parameter') in front of this command (so it also uses /dev/null).

sidenote: sdiff will show a side-by-side diff listings:

sdiff 1 2 
1                               1
2                               2
3                               3
4                               4
5                                  5
7                               7
                                  > 8
9                               9
10                              10
share|improve this answer
    
Thanks it works, but I dont understand what ... > /dev/null does in this context. The output of diff will goto /dev/null but isnt that nothing? –  Jiew Meng Aug 13 '11 at 13:48
1  
The diff will output all the differences between the files on your screen and >/dev/null makes sure the output of the command is redirected to oblivion. The if is still executed based on the output. –  Rinzwind Aug 13 '11 at 13:51
1  
The if statement checks the exit code of the diff command. 0 means no differences were found, while 1 means there were one or more differences. –  Knut Eldhuset May 15 '12 at 7:38

diff can even suppress output completely except for the "Files /bin/bash and /bin/sh differ" message using the code below.

file1="./helloworld$x.out"
file2="./output/helloworld$x.out"

if diff -q "$file1" "$file2"; then
    echo "Passed $x"
else
    echo "Failed $x"
fi

If you even want to hide that message, you've to append > /dev/null after the diff command to hide the output of diff:

if diff -q "$file1" "$file2" >/dev/null; then

/dev/null is a special file that acts as a blackhole, if you write to it, it'll be gone, if you're reading from it, you'll get nothing back.

Note that bash does not need ; to end lines.

As for the original question, to save the output of an program in a variable:

file1="./helloworld$x.out"
file2="./output/helloworld$x.out"
output="$(diff -q "$file1" "$file2)"

# the quotes are mandatory, this checks whether $output is empty or not
if [ -n "$output" ]; then
    echo "Passed $x"
else
    echo "Failed $x"
fi

Alternative ways to check whether a variable is empty:

[ "$output" = "" ]
[ "$output" == "" ]
[[ "$output" == "" ]]
[[ $output == "" ]]

If you're using Bash, the last two commands are recommended for string comparison. Otherwise, the first and [ -n "$output" ] is recommended.

share|improve this answer

a) The output of command1 can be catched with

output=$(diff "helloworld$x.out" "output/helloworld$x.out") 

or with backticks, but those are discouraged, because you can't nest them, and they might be hard to distinguish from apostrophs, depending on the font:

 output=`cmd1`

b) Instead of writing to a file, and then reading that file, (or grabbing the output, and then echoing it) you would use a pipe directly:

 cmd1 > file
 cat file | cmd2 

 output=$(cmd1)
 echo "${output}" | cmd2 

=>

 cmd1 | cmd2 

but in your example, you're not interested in the output, but the outcome of the program - did it work?

 diff "helloworld$x.out" "output/helloworld$x.out" && echo "success" || echo "failure" 

To read about the use of && and || search for "shortcut AND and shortcut OR".

To keep the output clean, you can redirect the output of 'diff' to nowhere:

 diff "helloworld$x.out" "output/helloworld$x.out" >/dev/null && echo "success" || echo "failure" 

To grab success and evaluate it later, you store the result of the last command in a variable with $?:

diff "helloworld$x.out" "output/helloworld$x.out" >/dev/null
result=$?
# do something else
case $result in 
   0) echo success ;;
   *) echo failure ;;
esac
share|improve this answer

If you want to know if two files are the same or differ (but don't care what the difference actually is), cmp is more suitable.

if cmp -s file1 file2; then echo "Equal"; else echo "Not equal"; fi
share|improve this answer

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.