blob: a5344ae7d6965da398e67c166cacf4650afd63f7 (
plain) (
blame)
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
|
# Move back up the directory tree to the first directory matching the name
bd() {
# Set positional parameters to an option terminator and what will hopefully
# end up being a target directory
set -- "$(
# Check there's no more than one argument
[ "$#" -le 1 ] || exit 1
# The requested pattern is the first argument, defaulting to just the
# parent directory
req=${1:-..}
# Strip trailing slashes if a trailing slash isn't the whole pattern
[ "$req" = / ] || req=${req%/}
# What to do now depends on the request
case $req in
# Just go straight to the root or dot directories if asked
/|.|..)
dirname=$req
;;
# Anything with a leading / needs to anchor to the start of the
# path. A strange request though. Why not just use cd?
/*)
dirname=$req
case $PWD in
"$dirname"/*) ;;
*) dirname='' ;;
esac
;;
# In all other cases, iterate through the PWD to find a match, or
# whittle the target down to an empty string trying
*)
dirname=$PWD
while [ -n "$dirname" ] ; do
dirname=${dirname%/*}
case $dirname in
*/"$req") break ;;
esac
done
;;
esac
# Check we have a target after all that
if [ -z "$dirname" ] ; then
printf >&2 'bd(): Directory name not in path\n'
exit 1
fi
# Print the target
printf '%s\n' "$dirname"
)"
# If the subshell printed nothing, return with failure
[ -n "$1" ] || return
# Try to change into the determined directory
command cd -- "$@"
}
|