-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathnormpath
executable file
·85 lines (78 loc) · 1.92 KB
/
normpath
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
#!/bin/sh
set -e
if [ $# -eq 0 ]
then
cat >&2 <<EOF
usage: `basename "$0"` PATH...
Canonicalize each of the PATHs, removing any unnecessary '..', '.', or '/'.
The paths are not required to exist physically.
EOF
exit 1
fi
# check whether `stringB` is not a prefix of `stringA`
#
# inputs:
# - 1: `stringA`
# - 2: `stringB`
#
not_prefix_of() {
case $1 in
"$2"*) return 1;;
*) return 0;;
esac
}
# remove `stringB` from the beginning of `stringA`; if `stringB` is not a
# prefix of `stringA`, `stringA` is returned instead
#
# this is a workaround for the absence of `${var##prefix}` or `${var#prefix}`
# in older shells; note however that this function does not allow patterns
#
# inputs:
# - 1: `stringA`
# - 2: `stringB`
#
# output:
# - ret: `stringA` with possibly `stringB` removed from the beginning
#
strip_prefix() {
# if the pattern is not a prefix of the original string, return unchanged
if not_prefix_of "$1" "$2"
then
ret=$1
else
# obtain substring
ret=`printf "%s" "$1" | wc -c`
ret=`expr "$ret" + 1`
ret=`printf '%s' "$1" | tail -c +"$ret"`
fi
}
# use more optimal form if supported
if ( _1=abcd && [ ${_1#ab} = cd ] ) >/dev/null 2>&1
then
strip_prefix() {
ret=${1#$2}
}
fi
for p
do
# strip '.'
pattern='\(^\|//*\)\.\(//*\|$\)'
while printf '%s' "$p" | grep >/dev/null "$pattern"
do
p=`printf '%s' "$p" | sed "s:$pattern:\1:g"`
done
# strip '..'
pattern='[^/]*//*\.\.\(//*\|$\)'
pre=
while printf '%s' "$p" | grep >/dev/null "$pattern"
do
pre=$pre`printf '%s' "$p" | sed 's:^\(\(\.\./\)*\)\(.*\):\1:'`
strip_prefix "$p" "$pre"
p=`printf '%s' "$ret" | sed "s:$pattern::"`
done
# strip extra '/'
p=`printf '%s' "$pre$p" | sed 's://*:/:g'`
# if there's nothing left, add a '.'
[ "$p" ] || p=.
printf '%s\n' "$p"
done