diff options
Diffstat (limited to 'misc/verifoo')
-rwxr-xr-x | misc/verifoo | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/misc/verifoo b/misc/verifoo new file mode 100755 index 0000000..34089cb --- /dev/null +++ b/misc/verifoo @@ -0,0 +1,110 @@ +#!/bin/sh + +help() { +cat << HELPDOC +usage: $(basename "$0") [options] [file]... + +OPTIONS: + -h, --help show this menu + -c, --check read and verify checksums from file + -r, --recursive produce a checksum for all files in a directory recursively + --recursive-sum produce a checksum for a directory. sensitive to filenames + --recursive-sum-nopath produce a checksum for a directory. not sensitive to filenames/placement + -s, --silent produce no output to stderr + -v, --verbose output a progress bar of hash progress if pv is avaliable (wip) + +MODES: + -S, --sha use sha1sum for checksums + -M, --md5 use md5sum for checksums + -X, --xxh use xxhsum for checksums (default if avaliable with sha1sum as fallback) +HELPDOC +} + +# set defaults +cat="pv -F'%r_[%b]_[%t]_[%e]_%p'" +! command -v pv >/dev/null && cat=cat + +hash=xxhsum +! command -v xxhsum >/dev/null && hash=sha1sum + +hashfiles="" +verbose=1 +recursive="" +outputfile="" + +while true; do + case "$1" in + -c|--check) [ -n "$2" ] && hashfiles="$hashfiles $2" && shift ;; + -s|--silent) verbose=0 ;; + -v|--verbose) verbose=2 ;; + --recursive|-r) recursive=3 ;; + --recursive-sum) recursive=2 ;; + --recursive-sum-nopath) recursive=1 ;; + -S|--sha) hash=sha1sum ;; + -M|--md5) hash=md5sum ;; + -X|--xxh) hash=xxhsum ;; + -h|--help) help; exit 0 ;; + -*) help; exit 1 ;; + *) break ;; + esac + shift +done + +case $verbose in + 0) cat=cat ;; + 1) cat=cat ;; +esac + +# run hash +while [ -n "$1" ]; do + if [ -d "$1" ]; then # is directory + # check if using -r flag + case "$recursive" in + 1) + # get hash of all files, sort hashes, hash hashes + # TODO make pv work in this mode + + #catd="$cat" + #if [ $verbose -ge 2 ] && [ "$catd" != "cat" ]; then + # total_files=$(du -a "$1" | wc -l) + # catd="pv -l -s$total_files -F'[%b/$total_files]_[%t]_[%e]_%p'" + #fi + #sum=`find "$1" -type f -print0 | xargs -r0 $hash | $catd | cut -d' ' -f1 | sort | $hash | cut -d' ' -f1` 2>/dev/null + sum=`find "$1" -type f -print0 | xargs -r0 $hash | cut -d' ' -f1 | sort | $hash | cut -d' ' -f1` 2>/dev/null + echo "r/$sum $1" + ;; + 2) + # hash sorted filenames + # sort all filenames w/ full path and hash + # hash those sums together + # `tar -c -f - "$1" | $hash` is a good idea but it doesn't work since changes to the fs affect tar + filehash=`find "$1" -type f -print0 | sort -z | xargs -r0 $cat | $hash | cut -d' ' -f1` + pathhash=`find "$1" -printf "%P\0" | sort -z | $hash | cut -d' ' -f1` + sum=`printf "$filehash$pathhash" | $hash | cut -d' ' -f1` + echo "p/$sum $1" + ;; + 3) + # sort files and hash each one in sequence + # TODO make pv work in this mode + find "$1" -type f -print0 | sort -z | xargs -r0 $hash + ;; + *) + [ $verbose -ge 1 ] && echo "-r not specified for directory $1. Exiting" + exit 1 + ;; + esac + else # is file + if ! [ -f "$1" ]; then + [ $verbose -gt 1 ] && echo "File $1 does not exist. Exiting" + exit 1 + fi + files="$1" + + while [ -f "$2" ]; do + files="$files\0$2" + shift + done + printf "$files" | xargs -r0 $hash + fi + shift +done |