blob: 1af694a321fac5c22c72c1250b3b982f73ce4d37 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
|
#!/bin/sh
NORM="\033[0m"
CYN="\033[0;36m"
GRN="\033[0;32m"
RED="\033[0;31m"
me="$(basename "$0")"
concat="pv -EE -F%r_[%b]_[%t]_[%e]_%p"
crypt=xxh
printhelp() {
cat << HELPDOC
Usage: $me [options] [file/directory]...
OPTIONS:
-o, --stdout Output checksum to STDOUT
-d, --compare Output checksum to STDOUT while displaying the progress
-S, --supress Supress all warnings and progress notes (default with -o)
-n, --no-progress Don't output progress bar (default with -o & -S)
-m, --md5 Create/verify md5 checksum
-s[mode], --sha[mode] Create/verify sha[mode] checksum
-x[mode], --xxh[mode] Create/verify xxh[mode] checksum (default)
-c [alg], --crypt [alg] Create/verify [alg] checksum (uses [alg]sum program; e.g. '-c sha256' uses sha256sum)
-v, --verify Verify files with existing checksums
-h, --help Print help
HELPDOC
}
while true; do
case "$1" in
-o|--stdout) stdout=1; nowarn=1; concat="cat" ;;
-d|--compare) stdout=1; nowarn=1; ;;
-S|--supress) nowarn=1; concat="cat" ;;
-n|--no-progressbar) concat="cat" ;;
-m|--md5) crypt=md5 ;;
-s*|--sha*) crypt=sha$(echo "$1" | tr -cd [:digit:]) ;;
-x*|--xxh*) crypt=xxh$(echo "$1" | tr -cd [:digit:]) ;;
-c|--crypt) crypt=$2 && shift ;; # Shift twice
-v|--verify) verify=1 ;;
-h|--help) printhelp; exit 0 ;;
-*) printhelp; exit 2 ;;
*) break ;;
esac
shift
done
hashalg=${crypt}sum
command -v $hashalg >/dev/null || (echo "Hashing algorithm '$hashalg' does not exist!" && exit 2)
# Warn user
if [ ! "$nowarn" ]; then
for file in "$@"; do
[ -d "$file" ] && echo "${RED}NOTE:${NORM} getting a checksum from an entire directory is NOT a standard feature in any other checksum-checking program! They can only be checked with this script!" && break
done
fi
# TODO Remove trailing / from args
while [ -n "$1" ]; do
file="$1"
[ ! "`echo "$file" | sed "s/.$crypt$//"`" = "$file" ] && shift && continue # Skip hash files
[ ! -e "$file" ] && echo "file '$file' does not exist!" && exit 1
[ -d "$file" ] && type=directory || type=file
hashfile="$file.$crypt"
[ -n "$verify" ] && [ ! -e "$hashfile" ] && shift && continue # Skip files without a hash in verify mode
[ ! "$nowarn" ] && echo "Getting $crypt checksum of $type '$file'..."
hash=`find "$file" -type f -print0 | sort -z | xargs -r0 $concat | $hashalg | cut -d' ' -f1`
if [ "$stdout" ]; then
echo "$hash ($crypt) $file"
else
if [ -e "$hashfile" ]; then
phash=`cat "$hashfile"`
[ $phash = $hash ] \
&& echo "${GRN}Success: $type matches saved checksum!" \
|| (echo "${RED}Error: $type does not match saved checksum!\nExpected checksum: $phash\nActual checksum: $hash" && ec=1)
else
echo $hash > "$hashfile" \
&& echo "${CYN}$crypt checksum file saved at '$hashfile'!" \
|| (echo "${RED}'$hashfile' could not be created!\n$crypt checksum of $type '$file' is $hash" && ec=1)
fi
printf "$NORM"; [ -n "$2" ] && echo
fi
shift
done
exit $ec
|