dotfiles

configuration files for shell, text editor, graphical environment, etc.
git clone git://src.adamsgaard.dk/dotfiles # fast
git clone https://src.adamsgaard.dk/dotfiles.git # slow
Log | Files | Refs | README | LICENSE Back to index

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