detect_file_changes (3210B)
1 #!/bin/sh 2 3 # Specify the file name for storing the file checksums 4 chksumfile=.checksums.txt 5 6 # Choice of tool for generating and verifying checksums 7 hashgen=sha256sum 8 9 function show_help { 10 cat <<-END 11 Usage: ${0##*/} [OPTIONS] [FILE] 12 Detect changes to files and directory contents using $hashgen checksums. 13 Unlike Git and similar, this program does not store file version history. 14 15 On the first run, the program stores the directory contents and the file 16 cryptographic checksums in a '$chksumfile' file in the current directory. During 17 subsequent runs, the directory contents and files are compared to the these 18 stored values. 19 20 Options: 21 -h, --help show this message 22 - list all files and their checksums to stdout 23 -a, --add FILE update the stored checksum value of FILE 24 -r, --reset reset the values $chksumfile to the current state, which is 25 identical to calling '--add FILE' to all files 26 27 This program exits with return status 0 if no changes are found to the stored 28 state, and 1 if changes are detected. 29 30 Author: Anders Damsgaard anders@adamsgaard.dk, License: GPLv3+ 31 END 32 } 33 34 if [ "$1" = "-h" ] || [ "$1" = "--help" ]; then 35 show_help 36 exit 0 37 fi 38 39 # Return checksums for all files in all subdirectories 40 generate_checksums() { 41 find . -type f `# search files in all subdirectories` \ 42 ! -name "$chksumfile" `# ignore the checksumfile itself` \ 43 ! -name "${0##*/}" `# ignore this file` \ 44 ! -name ".*.swp" `# ignore editor swap files` \ 45 -exec "$hashgen" '{}' + `# run hash command on every found file` 46 } 47 48 check_if_file_exists() { 49 if [ ! -f "$1" ]; then 50 (<&2 echo "Error: file '$1' was not found") 51 exit 2 52 fi 53 } 54 55 update_checksum() { 56 file=${1//\//\\\/} # escape forward slashes 57 file=${file//\./\\.} # escape periods 58 file=${file// /\\ } # escape spaces 59 # sed -i '' "s/^.* \*\.$file/$($hashgen $1) *.\/$file/" "$2" 60 grep "$file" "$2" 61 sed -i '' "s/.*\ $file/asdf/" "$2" 62 63 } 64 65 if [ ! -f "$chksumfile" ] || [ "$1" = "-r" ] || [ "$1" = "--reset" ]; then 66 # (Over-)write checksum file 67 generate_checksums > "$chksumfile" 68 echo "Checksums stored in $chksumfile" 69 70 elif [ "$1" = "-a" ] || [ "$1" = "--add" ]; then 71 for file in "${@:2}"; do 72 check_if_file_exists "$file" 73 done 74 # Update checksums for all specified files 75 for file in "${@:2}"; do 76 update_checksum "$file" "$chksumfile" 77 done 78 79 elif [ "$1" = "-" ]; then 80 # Print checksums and file paths to stdout 81 generate_checksums 82 83 else 84 # Compare current checksums against stored values 85 generate_checksums \ 86 | diff "$chksumfile" - `# compare stored checksums with current vals` \ 87 | sed 's/>/new: /' `# replace > with new:` \ 88 | sed 's/</rem: /' `# replace < with rem:` \ 89 | sed 's/\*\.\///' `# simplify file path` 90 #| awk '{ print $1 $3 }' `# hide checksum in second column` \ 91 92 # Report if the diff command returned with status 0 93 if [ ${PIPESTATUS[1]} -eq 0 ]; then 94 echo "No file changes detected" 95 else 96 # Return exit status 1 if something changed 97 exit 1 98 fi 99 fi