/
pathsetup
executable file
·156 lines (139 loc) · 4.4 KB
/
pathsetup
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#!/bin/sh
pathsetuplog() {
true
}
set -e
if test "$PATHSETUPTRACE"; then
set -x
fi
if test "$PATHSETUPLOG"; then
if ! test -e "$PATHSETUPLOG"; then
touch "$PATHSETUPLOG"
fi
pathsetuplog() {
echo "$@" >> "$PATHSETUPLOG"
}
fi
set -u
cmdname=`basename "$0"`
usage() {
cat <<ENDUSAGE
Usage: $cmdname <PATHSTR> [EXCLUDE]
Set up a PATH-like string
ARGUMENTS
<PATHSTR> A string containing paths to check,
separated by either colons or newlines.
[EXCLUDE] A string containing paths to exclude,
separated by either colons or newlines.
This is useful for excluding paths which are managed by other tools,
like /Users/YOU/.nvm.
Paths are matched with case statements,
so use globs to do things like match all children of a directory.
VARIABLES
\$PATHSETUPTRACE
If set, set -x will be enabled.
\$PATHSETUPLOG
If set, assume it points to a file path, and log debugging information
to that file.
Each log line will have a prefix.
Basic messages:
+ Path added to the output
- Path excluded from output based on EXCLUDE
* Path specified twice in PATHSTR
! Path does not exist
x The exclusion list as passed to the command (printed once before execution)
< The path list as passed to the command (printed once before execution)
> The output of the command (printed once after execution)
Verbose messages:
___p The path from input being processed
__xx The exclusion pattern matched the path
__x! The exclusion pattern didn't match the path
___> The output of the command at this point in time
OUTPUTS
Return a string continaing only the existing directories from PATHSTR,
separated by colons.
Can set PATH to this output.
EXAMPLES
> pathsetup "/bin:/nonexistent:/sbin"
/bin:/sbin
> PATHSETUPLOG=$HOME/pathsetup.log pathsetup "/bin:/nonexistent:/sbin"
/bin:/sbin
> ls $HOME/pathsetup.log
pathsetup.log
ENDUSAGE
}
# Convert pathlike variables to newline separated patterns,
# and strip all leading or trailing separators.
pathlike2linesep() {
echo "$1" | tr ':' '\n' | sed 's/^|*//;s/|*$//'
}
# Test whether a path-like variable contains a specific path.
# Only consider colon-separated paths, not newline-separated paths.
# Usage: pathcontains "$PATH" "/bin"
pathcontains() {
pathlike=":$1:"
p="$2"
test "${pathlike#*":$p:"}" != "$pathlike"
}
pathlike=
exclude=
while test $# -gt 0; do
case "$1" in
-h | --help ) usage; exit 0;;
*)
if test -z "$pathlike"; then
pathlike="$(pathlike2linesep "$1")"
elif test -z "$exclude"; then
exclude="$(pathlike2linesep "$1")"
else
echo "Unknown argument: $1"
usage
exit 1
fi
shift
;;
esac
done
pathsetuplog "$(echo "$pathlike" | tr ':' '\n' | sed 's/^/< /g')"
pathsetuplog "$(echo "$exclude" | tr ':' '\n' | sed 's/^/x /g')"
outpath=
initialifs="$IFS"
IFS='
'
for path in $pathlike; do
if test -z "$path"; then
continue
elif ! test -d "$path"; then
pathsetuplog "! $path"
continue
fi
pathsetuplog "___p $path"
pathsetuplog "$(echo "$outpath" | tr ':' '\n' | sed 's/^/___> /g')"
ignore=
if pathcontains "$outpath" "$path"; then
pathsetuplog "* $path"
else
ignore=
set -f # Disable file globbing so that the shell doesn't expand * characters in the for statement
for pattern in $exclude; do
case "$path" in
# Because we disable globbing above, case will see any * characters and use them for pattern matching instead of file globbing
$pattern)
pathsetuplog "__xx $path $pattern"
ignore=1
break
;;
*)
pathsetuplog "__x! $path $pattern"
esac
done
set +f # Re-enable file globbing
if test -z "$ignore"; then
pathsetuplog "+ $path"
outpath="${outpath}:${path}"
fi
fi
done
IFS="$initialifs"
pathsetuplog "$(echo "$outpath" | tr ':' '\n' | sed 's/^/> /g')"
echo "$outpath"