6

I want to redirect the output of a command (diff in this case) to a file but only if there is a difference in files I'm comparing. For example, imagine I have three files a, b, and c where a and b are equivalent but a and c are not.

If I do diff a c > output.txt or diff a b > output.txt, regardless of whether there is a difference or not, output.txt will be created. I only want output.txt to be created if there is a diff (i.e, diff returns 1).

I'd want to do something like:

if ! diff a c > /dev/null; then
    diff a c > output.txt
fi

But without running the command twice. I could save the contents of the command like so:

res=$(diff a c)
if [ $? != 0 ]; then
    echo "$res" > output.txt
fi

But then I'm bringing echo into this as a "middle-man", which could potentially raise some issues. How can I redirect output/create a file only if there's output without duplicating code?

5
  • 1
    I don't see any issue with the echo solution
    – jesse_b
    Jun 14, 2019 at 13:10
  • 1
    @Jesse_b I guess I'm being paranoid because of this SO question. While the issues shown here won't really be evident in my example (using diff), it could fail for other commands. I could use the printf solution, but I was just wondering if there was any way to avoid saving to a variable and immediately printing it afterwards
    – TerryA
    Jun 14, 2019 at 13:18
  • 1
    Yeah if you want to avoid that issue you could use printf or echo -- to specify the end of options. You could also use cat.
    – jesse_b
    Jun 14, 2019 at 13:21
  • A simple temporary file? Delete it if not needed or copy in place if needed.
    – andcoz
    Jun 14, 2019 at 13:30
  • You need to save the output somewhere, if you want to conditionally discard it. Please edit the question to clarify the issues.
    – muru
    Jun 14, 2019 at 14:13

3 Answers 3

9

You could call the command once, redirect the output, then remove the output if there were no differences:

diff a c > output.txt && rm output.txt
0
6

diff is a relatively expensive command, at least if the files are different. Calculating a minimal set of changes is (relatively) CPU intensive. So its understandable not to want to do that twice.

cmp, however, is cheap, CPU-wise. Presuming these files are of a reasonable size (I doubt you'd call diff on multi-GB files), it will have almost no performance cost—and might even be quicker in the files identical case.

if ! cmp -s a c; then # -s = silent, do not print results to console
    diff a c > output.txt
fi
0
5

What about temporary file?

diff a c > /tmp/output.txt
if [ $? != 0 ]; then mv /tmp/output.txt /my/folder/output.txt; else rm -f /tmp/output.txt; fi

replace the -f with -i if you want delete confirmation dialog.

This way you only run command twice, no temporary variables and no 'middleman' be it echo, printf or anything else.

0

You must log in to answer this question.

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