-
Notifications
You must be signed in to change notification settings - Fork 1
/
ddiff
executable file
·107 lines (96 loc) · 2.97 KB
/
ddiff
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
#!/bin/bash
# Directory/file-wise diff. Compares file/folder names. Does not compare file contents.
#
# author: andreasl
script_name="${0##*/}"
IFS= read -r -d '' script_description << HELP_EOF
${script_name}
Compare file trees in a readable format using find, sort, comm and sed.
Usage:
${script_name} [OPTIONS] <dir1> <dir2>
${script_name} <dir1> <dir2> [OPTIONS]
Options:
-1, --in-1: Only show lines that are in dir1.
-2, --in-2: Only show lines that are in dir2.
-C, --no-color: Disable colored output.
-d, --only-different: Show only directories/files that exist only in dir1 or only in dir2.
-e <pattern>, --exclude <pattern>: Exclude glob pattern <pattern>, e.g. "*.git".
-h, --help: Print the help message.
-s --only-same: Show only directories/files that exist in both dir1 and dir2.
Same as -1 -2.
Examples:
${script_name} -e "*.git" -C -d dev dev_backup
${script_name} ~/Photos ~/Media -s
${script_name} --help
HELP_EOF
# parse command line arguments
excludes=()
must_be_in_1=false
must_be_in_2=false
only_different=false
only_same=false
source_dir=.
target_dir=.
use_colors=true
while [ "$#" -gt 0 ]; do
case "$1" in
-1|--in-1)
must_be_in_1=true
;;
-2|--in-2)
must_be_in_2=true
;;
-C|--no-color)
use_colors=false
;;
-d|--only-different)
only_different=true
;;
-e|--exclude)
excludes+=(-path "$2" -prune -o)
shift
;;
-h|--help)
printf -- "$script_description"
exit 0
;;
-s|--only-same)
only_same=true
;;
*) # unknown option
source_dir="$1"
shift
target_dir="$1"
;;
esac
shift
done
# get the file trees and do the comparisons
tree1="$(find "$source_dir" "${excludes[@]}" -printf "%P\n" | sort)"
tree2="$(find "$target_dir" "${excludes[@]}" -printf "%P\n" | sort)"
output="$(comm <(printf '%s\n' "$tree1") <(printf '%s\n' "$tree2"))"
# postprocess the output from comm
output="$(sed -E "s:(^[^\t].*):1 \1:g" <<< "$output")"
output="$(sed -E "s:^\t{2}(.*):3 \1:g" <<< "$output")"
output="$(sed -E "s:^\t{1}(.*):2 \1:g" <<< "$output")"
# filter the output
if [ "$must_be_in_1" == true ] || [ "$only_same" == true ]; then
output="$(sed '/^2 /d' <<< "$output")"
fi
if [ "$must_be_in_2" == true ] || [ "$only_same" == true ]; then
output="$(sed '/^1 /d' <<< "$output")"
fi
if [ "$only_different" == true ]; then
output="$(sed '/^3 /d' <<< "$output")"
fi
# colorize output
if [ "$use_colors" == true ]; then
red='\\e[31m'
green='\\e[32m'
orange='\\e[33;1m'
nc='\\e[0m'
output="$(sed -E "s:^1 (.*):${red}1 \1${nc}:g" <<< "$output")"
output="$(sed -E "s:^2 (.*):${green}2 \1${nc}:g" <<< "$output")"
output="$(sed -E "s:^3 (.*):${orange}3 \1${nc}:g" <<< "$output")"
fi
printf '%b\n' "$output"