summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Xu (Hello71) <alex_y_xu@yahoo.ca>2022-03-06 13:47:57 -0500
committerAlex Xu (Hello71) <alex_y_xu@yahoo.ca>2022-03-06 13:47:57 -0500
commit796db64fcb1024278da4cc9989c055b694226459 (patch)
tree73d5a6e3e719aa377653be46e6202954768eb341
parent9d114fbd59ca30a67150421292d57db39d158649 (diff)
downloadnextbin-796db64fcb1024278da4cc9989c055b694226459.tar.xz
nextbin-796db64fcb1024278da4cc9989c055b694226459.zip
reimplement using test -ef
handles symlinks more logically and is also twice as fast
-rwxr-xr-xnextbin56
1 files changed, 29 insertions, 27 deletions
diff --git a/nextbin b/nextbin
index 31241ef..3a7a4e6 100755
--- a/nextbin
+++ b/nextbin
@@ -23,30 +23,32 @@ orig_exe=$1
shift
exe_name=${orig_exe##*/}
-case ":$PATH:" in
- ::) die 'empty PATH not supported' ;;
- *:[!/]*) die 'relative PATH elements not supported' ;;
- *:*/./*:*|*:*/../*:*) die 'PATH elements containing . or .. not supported' ;;
-esac
-
-case $orig_exe in
- # theoretically this could be optimized but it's negligible cost
- */*) orig_dir=$(cd -L "${orig_exe%/*}" && pwd -L) ;;
- *) orig_dir=$PWD ;;
-esac
-
-# clean up path. theoretically we could allow e.g. PATH=/dir://dir but which
-# would we match for cd /dir; ./exe
-tmp_path=$(printf '%s\n' ":$PATH:" | sed -e 's|/*:|:|g' -e 's|//|/|g')
-
-case $tmp_path in
- *:$orig_dir:$orig_dir:*|*:$orig_dir:*:$orig_dir:*)
- die 'duplicate entry in PATH: %s' "$orig_dir"
-esac
-
-new_path=${tmp_path#*":$orig_dir:"}
-new_path=${new_path%:}
-exe=$(PATH="$new_path" command -v "$exe_name") || true
-[ -n "$exe" ] || die 'PATH lookup failed using %s' "$new_path"
-
-$action "$exe" "$@"
+[ -n "$PATH" ] || die 'PATH is empty'
+
+path=$PATH
+phase=1
+found=
+while :; do
+ exe=${path%%:*}/$exe_name
+ if [ -f "$exe" ] && [ -x "$exe" ]; then
+ if [ "$phase" = 1 ]; then
+ if [ "$exe" -ef "$orig_exe" ]; then
+ phase=2
+ fi
+ elif [ "$exe" -ef "$orig_exe" ]; then
+ if [ -n "$found" ]; then
+ die 'duplicate PATH entries found'
+ fi
+ elif [ -z "$found" ]; then
+ found=$exe
+ fi
+ fi
+ case $path in
+ *:*) path=${path#*:} ;;
+ *) break ;;
+ esac
+done
+
+[ "$phase" != 1 ] || found=$(command -v "$exe_name") || die '%s is not in PATH' "$orig_exe"
+[ -n "$found" ] || die '%s is last instance' "$orig_exe"
+$action "$found" "$@"