diff options
author | Alex Xu (Hello71) <alex_y_xu@yahoo.ca> | 2022-03-06 13:47:57 -0500 |
---|---|---|
committer | Alex Xu (Hello71) <alex_y_xu@yahoo.ca> | 2022-03-06 13:47:57 -0500 |
commit | 796db64fcb1024278da4cc9989c055b694226459 (patch) | |
tree | 73d5a6e3e719aa377653be46e6202954768eb341 | |
parent | 9d114fbd59ca30a67150421292d57db39d158649 (diff) | |
download | nextbin-796db64fcb1024278da4cc9989c055b694226459.tar.xz nextbin-796db64fcb1024278da4cc9989c055b694226459.zip |
reimplement using test -ef
handles symlinks more logically and is also twice as fast
-rwxr-xr-x | nextbin | 56 |
1 files changed, 29 insertions, 27 deletions
@@ -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" "$@" |