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
|