summaryrefslogtreecommitdiff
path: root/misc/verifoo
blob: 34089cbcab3a36061e15830ab3dc196738fd19b1 (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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
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