aboutsummaryrefslogtreecommitdiff
path: root/sh
diff options
context:
space:
mode:
authorTom Ryder <tom@sanctum.geek.nz>2017-05-26 20:24:13 +1200
committerTom Ryder <tom@sanctum.geek.nz>2017-05-26 20:24:13 +1200
commit2d0fefe4cde7831c7e49641df217ee0354751a63 (patch)
tree8496cac55c27fe5952f0ef8e50c9180712353d67 /sh
parent520f9e174aa0569a95469a7d2b746582bdf0c18c (diff)
downloaddotfiles-2d0fefe4cde7831c7e49641df217ee0354751a63.tar.gz
Reimplement ud()
More fault-tolerant and no subshell or temporary vars
Diffstat (limited to 'sh')
-rw-r--r--sh/shrc.d/ud.sh62
1 files changed, 30 insertions, 32 deletions
diff --git a/sh/shrc.d/ud.sh b/sh/shrc.d/ud.sh
index 79f4b5e7..a3997702 100644
--- a/sh/shrc.d/ud.sh
+++ b/sh/shrc.d/ud.sh
@@ -2,48 +2,46 @@
# like cd .., cd ../.., etc
ud() {
- # Check argument count
- if [ "$#" -gt 1 ] ; then
+ # Check arguments; default to 1 and $PWD
+ if [ "$#" -gt 2 ] ; then
printf >&2 'ud(): Too many arguments\n'
return 2
fi
+ set -- "${1:-1}" "${2:-"$PWD"}"
+ set -- "$1" "$2"
- # Check first argument, number of steps upward, default to 1.
- # "0" is weird, but valid; "-1" however makes no sense at all
- if [ "${1:-1}" -lt 0 ] ; then
+ # Check first argument, number of steps upward. "0" is weird, but valid;
+ # "-1" however makes no sense at all
+ if [ "$1" -lt 0 ] ; then
printf >&2 'ud(): Invalid step count\n'
return 2
fi
- # Change the positional parameters from the number of steps given to a
- # "../../.." string
- set -- "$(
-
- # Append /.. to the target (default PWD) the specified number of times
- dirname=${2:-"$PWD"}
- i=0
- steps=${1:-1}
- while [ "$i" -lt "$steps" ] ; do
- dirname=${dirname%/}/..
- i=$((i+1))
+ # Check second argument, starting path, for relativity and anchor it if
+ # need be
+ case $2 in
+ /*) ;;
+ *) set -- "$1" "$PWD"/"$2" ;;
+ esac
+
+ # Chop an element off the target the specified number of times
+ while [ "$1" -gt 0 ] ; do
+
+ # Make certain there are no trailing slashes to foul us up
+ while : ; do
+ case $2 in
+ */) set -- "$1" "${2%/}" ;;
+ *) break ;;
+ esac
done
- # Check we have a target after all that
- if [ -z "$dirname" ] ; then
- printf >&2 'ud(): Destination construction failed\n'
- exit 1
- fi
+ # Strip a path element
+ set -- "$(($1-1))" "${2%/*}"
+ done
- # Print the target with trailing slash to work around newline stripping
- printf '%s/' "${dirname%/}"
- )"
+ # Shift off the count, which should now be zero
+ shift
- # Remove trailing slash
- set -- "${1%/}"
-
- # If the subshell printed nothing, return with failure
- [ -n "$1" ] || return
-
- # Try to change into the determined directory
- command cd -- "$@"
+ # Try to change into the determined directory, or the root if blank
+ command cd -- "${1:-/}"
}