blob: 1043a8cb0d25740a0abae5028ad1aada4a197395 (
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
65
66
67
|
# Move back up the directory tree to the first directory matching the name
bd() {
# Check argument count
if [ "$#" -gt 1 ] ; then
printf >&2 'bd(): Too many arguments'
return 2
fi
# Set positional parameters to an option terminator and what will hopefully
# end up being a target directory
set -- "$(
# The requested pattern is the first argument, defaulting to just the
# parent directory
req=${1:-..}
# Strip trailing slashes if a trailing slash is not 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 -- "$@"
}
|