2

I tried to compare two files and output customized string. Following is my script.

#!/bin/bash

./${1} > tmp

if ! diff -q tmp ans.txt &>/dev/null; then
    >&2 echo "different"
else
    >&2 echo "same"
fi

When I execute script, I get:

sh cmp.sh ans.txt
different
Files tmp and ans.txt differ

The weird part is when I type diff -q tmp ans.txt &>/dev/null. No output will show up.

How to fix it(I don't want line:"Files tmp and ans.txt differ")? Thanks!

14
  • use cmp to compare files. ./${1} > tmp should result in running ans.txt as a command - don't you get "permission denied" or other error on that line? Commented Sep 11, 2020 at 14:23
  • 1
    You are executing your command with sh - what is your implementation of sh? Does the problem persist when running under bash? Commented Sep 11, 2020 at 14:28
  • 2
    Yes, cmp is better than diff when you only want to know if files are different, but don't care about generating a patch to transform one file to the other. Commented Sep 11, 2020 at 14:34
  • 1
    ...also, cmp -s exists so you don't need to redirect stdout and stderr at all; if cmp -s file1 file2; then echo "Files are identical"; else echo "Files are different"; fi Commented Sep 11, 2020 at 14:35
  • 1
    @Steven, /bin/sh and /bin/bash behave differently even if they're both provided by bash (but it's on systems where /bin/sh is provided by ash, dash, etc. that the differences get really big). If you're using bash-only syntax, always use #!/bin/bash or #!/usr/bin/env bash, not #!/bin/sh. Commented Sep 11, 2020 at 14:36

1 Answer 1

3

Most probably the version of sh you are using doesn't understand the bash (deprecated/obsolete) extension &> that redirect both stdout and stderr at the same time. In posix shell the command &>/dev/null I think is parsed as { command & }; > /dev/null - it results in running the command in the background & and the > /dev/null part I think is ignored, as it just redirect output of a nonexistent command - it's valid syntax, but executes nothing. Because running the command in the background succeeds, the if always succeeds.

Prefer not to use &> - use >/dev/null 2>&1 instead. Use diff to pretty print the files comparison. Use cmp in batch scripts to compare files.

if cmp -s tmp ans.txt; then
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for for mentioning this page: Obsolete and deprecated syntax [Bash Hackers Wiki (DEV 20200708T2203)]: wiki-dev.bash-hackers.org/scripting/obsolete . It is worth reading in detail. Note that these guidelines deprecate not only &>, but also set -euo pipefail, previously recommended by some, e.g., Bash Strict Mode: redsymbol.net/articles/unofficial-bash-strict-mode . Not everyone may be aware of these changing recommendations.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.