Keep running command until output differs from previous run in Bash

From man 1 watch:

-g, --chgexit
Exit when the output of command changes.

watch is not required by POSIX but it's quite common anyway. In Debian or Ubuntu it's in the procps package along with kill and ps (and few other tools).

Example:

watch -g -n 5 'date +%H:%M'

This should do the trick - explanations inline:

#!/usr/bin/env bash

# Exit if any errors occur or any undefined variables are dereferenced
set -o errexit -o nounset

# Store the outputs in a separate directory
output_directory="$(mktemp --directory)"
last_output_file="${output_directory}/last"
current_output_file="${output_directory}/current"
touch "$current_output_file"
ln --symbolic "$current_output_file" "$last_output_file"
# The count is just here to show that we always run at least twice, and that
# after that we run the command a random number of times.
count=0

while true
do
    echo "$((++count))"

    # This is our command; it prints 0 or 1 randomly
    if [[ "$RANDOM" -gt 16383 ]]
    then
        echo 0 > "$current_output_file"
    else
        echo 1 > "$current_output_file"
    fi

    # Abort the loop when the files differ
    if ! diff --brief "$last_output_file" "$current_output_file"
    then
        break
    fi

    # Shunt the current output to the last
    mv "$current_output_file" "$last_output_file"
done

There are probably simpler ways to do this, but it has a couple useful features:

  • It avoids creating any extraneous files, such as using mktemp for every output.
  • By starting with the last output file being a symbolic link to the current output file we guarantee that the first diff command sees two identical files. This avoids duplicating the command we're testing for, at the expense of one extra diff execution.