diff options
author | Kerin Millar <kfm@plushkava.net> | 2024-06-03 11:58:44 +0100 |
---|---|---|
committer | Kerin Millar <kfm@plushkava.net> | 2024-06-12 08:06:42 +0100 |
commit | d6b03b9ae75d0e76a2620e227cf24d9bcdb5e321 (patch) | |
tree | 9d95260a0e089259b9944a36b532dbb6ca37dd27 | |
parent | Add the hr() function to print a horizontal rule (diff) | |
download | gentoo-functions-d6b03b9ae75d0e76a2620e227cf24d9bcdb5e321.tar.gz gentoo-functions-d6b03b9ae75d0e76a2620e227cf24d9bcdb5e321.tar.bz2 gentoo-functions-d6b03b9ae75d0e76a2620e227cf24d9bcdb5e321.zip |
Add the whenceforth() function as a type -P alternative
It acts much as type -P does in bash. I would have liked to name it
whence but ksh and zsh already have builtins by that name.
Signed-off-by: Kerin Millar <kfm@plushkava.net>
-rw-r--r-- | functions.sh | 48 | ||||
-rwxr-xr-x | test-functions | 39 |
2 files changed, 85 insertions, 2 deletions
diff --git a/functions.sh b/functions.sh index c077290..504ee9e 100644 --- a/functions.sh +++ b/functions.sh @@ -566,6 +566,51 @@ warn() } # +# Considers the first parameter as the potential name of an executable regular +# file before attempting to locate it. If not specifed as an absolute pathname, +# a PATH search shall be performed in accordance with the Environment Variables +# section of the Base Definitions. If an executable is found, its path shall be +# printed. Otherwise, the return value shall be 1. This function is intended as +# an alternative to type -P in bash. That is, it is useful for determining the +# existence and location of an external utility without potentially matching +# against aliases, builtins and functions (as command -v can). +# +whenceforth() +( + local bin path prefix + + case $1 in + /*) + # Absolute command paths must be directly checked. + [ -f "$1" ] && [ -x "$1" ] && bin=$1 + ;; + *) + # Relative command paths must be searched for in PATH. + # https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_03 + case ${PATH} in + ''|*:) + path=${PATH}: + ;; + *) + path=${PATH} + esac + IFS=: + set -f + for prefix in ${path}; do + case ${prefix} in + */) + bin=${prefix}$1 + ;; + *) + bin=${prefix:-.}/$1 + esac + [ -f "${bin}" ] && [ -x "${bin}" ] && break + done + esac \ + && printf '%s\n' "${bin}" +) + +# # Determines whether the first parameter is truthy. The values taken to be true # are "yes", "true", "on" and "1", whereas their opposites are taken to be # false. The empty string is also taken to be false. All pattern matching is @@ -876,8 +921,7 @@ fi # Store the path to the true binary. It is potentially used by _update_columns. if [ "${BASH}" ]; then - # shellcheck disable=3045 - genfun_bin_true=$(type -P true) + genfun_bin_true=$(whenceforth true) fi # Store the name of the GNU find binary. Some platforms may have it as "gfind". diff --git a/test-functions b/test-functions index d90462e..813d524 100755 --- a/test-functions +++ b/test-functions @@ -507,6 +507,44 @@ test_hr() { iterate_tests 5 "$@" } +test_whenceforth() { + set -- \ + ge 1 PATH N/A \ + ge 1 PATH . \ + ge 1 PATH rather-unlikely-to-exist \ + ge 1 PATH /var/empty \ + ge 1 PATH /var/empty/nofile \ + eq 0 PATH /bin/sh \ + eq 0 PATH sh \ + eq 0 '' newer/file \ + eq 0 . newer/file \ + eq 0 :/var/empty/x newer/file \ + eq 0 /var/empty/x: newer/file \ + eq 0 /var/empty/x::/var/empty/y newer/file \ + ge 1 '' older/file \ + ge 1 . older/file \ + ge 1 :/var/empty/x older/file \ + ge 1 /var/empty/x: older/file \ + ge 1 /var/empty/x::/var/empty/y older/file + + chmod +x newer/file + + callback() { + shift + path=$1 + shift + test_description="whenceforth $(_print_args "$@")" + if [ "${path}" = PATH ]; then + whenceforth "$@" >/dev/null + else + PATH=${path} whenceforth "$@" >/dev/null + fi + } + + iterate_tests 4 "$@" +} + + iterate_tests() { slice_width=$1 shift @@ -571,6 +609,7 @@ test_srandom || rc=1 test_newest || rc=1 test_trim || rc=1 test_hr || rc=1 +test_whenceforth || rc=1 cleanup_tmpdir |