Skip to content

Instantly share code, notes, and snippets.

@PeterJRiches
Created June 21, 2025 20:55
Show Gist options
  • Select an option

  • Save PeterJRiches/60fabea98db10ab4aa7fd533b33bbd88 to your computer and use it in GitHub Desktop.

Select an option

Save PeterJRiches/60fabea98db10ab4aa7fd533b33bbd88 to your computer and use it in GitHub Desktop.
Detect whether a directory tree has changed (in bash, without diff)
# hash_the_dir ()
# Hash all the files in the given directory to produce one checksum.
# (Useful for checking for any file's contents or name being changed.)
# Parameter: directory
# Output: md5sum of the names and contents of all the files, recursively.
hash_the_dir() {
# The options below are to make the archive deterministic:
# i.e. same files, same hash; not affected by metadata (like timestamps),
# nor by any changes to the git repo, if present (like commits).
local error="Error calling hash_the_dir"
[ ${#} -eq 0 ] && {
echo "$error: no arguments passed. Expected a directory." >&2
return 1
}
[ -d "$1" ] || {
echo "$error: '$1' is not a directory!" >&2
return 1
}
tar --sort=name \
--format=posix \
--mtime='@0' \
--owner=0 --group=0 --numeric-owner \
--pax-option=delete=atime,delete=ctime \
--exclude=.git \
-cf - "$1" | md5sum | sed 's/ -$//'
}
# changes_files ()
# Takes a command as an argument, executes it, and sees whether any
# files in the current working directory are changed.
# Parameter: command to execute
# Exit value:
# 0 if any file under the cwd is changed/moved/added/deleted
# 1 if all the files are the same.
# Depends on: hash_the_dir ()
changes_files() {
local -r command="$*"
local hash1
local hash2
hash1="$(hash_the_dir ".")" # snapshot before running command
(
# shellcheck disable=SC1090 # because can't static-check a variable command!
. <(echo "$command")
)
hash2="$(hash_the_dir ".")" # snapshot after running command
# if [[ "$hash1" == "$hash2" ]]; then
if [ "$hash1" = "$hash2" ]; then
return 1 # hashes matched, therefore nothing changed
else
return 0 # something changed between the two hashes
fi
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment