25

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?

4 Answers 4

20

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
3
  • 1
    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, 2011 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, 2011 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. May 15, 2012 at 7:38
18

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.

6

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
3

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

You must log in to answer this question.

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