Created
June 21, 2025 20:55
-
-
Save PeterJRiches/60fabea98db10ab4aa7fd533b33bbd88 to your computer and use it in GitHub Desktop.
Detect whether a directory tree has changed (in bash, without diff)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # 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