Require_once For Bash, But How To For Older Bash And POSIX-shell?
Inspired by the Php require_once
I figured how it could be implemented for modern Bash with associative arrays here:
a.sh
#!/usr/bin/env bash
declare -gAi __REQUIRES
require_once() {
for p; do
r=$(readlink --canonicalize-existing "$p")
# shellcheck disable=SC1090 # Dynamic source
[[ -r "$r" && 1 -ne "${__REQUIRES[$r]}" ]] && __REQUIRES[$r]=1 && . "$r"
done
}
require_once ./b.sh
require_once ./b.sh
hello
b.sh
hello() {
printf 'I am the hello function in b.sh.\n'
}
This works as intended:
- Get the real path of the
source
. - Check it is readable, check it is not already loaded by looking-up the global associative array key.
- If so, register it in the global associative array and source it.
Now I am still wondering how to:
- Get the real path of the source in a more portable/standard way not depending on Linux Gnu Tools?
- Have it work with older Bash like 3.2
- Have it work with POSIX-shell grammar without array.
Answer
Get the real path of the source in a more portable/standard way not depending on Linux Gnu Tools?
readlink -f
is available on Busybox. Do readlink
after checking that the path exists.
Anyway, https://www.google.com/search?q=readlink+POSIX -> https://medium.com/mkdir-awesome/posix-alternatives-for-readlink-21a4bfe0455c , https://github.com/ko1nksm/readlinkf .
Have it work with older Bash like 3.2
Have it work with POSIX-shell grammar without array.
POSIX does not like newlines in filenames anyway, so just store files as lines:
__REQUIRES=""
if ! printf "%s" "$__REQUIRES" | grep -Fq "$r"; then
__REQUIRES="$__REQUIRES""$r
"
. "$r"
fi
Or maybe use case so that you do not fork
:
__REQUIRES="
"
case "$__REQUIRES" in
*"
$r
"*) ;;
*)
__REQUIRES="$__REQUIRES""$r
"
. "$r"
;;
esac
If you want to handle newlines in filenames, convert filename via xxd
or od
(both are available on Busybox, od
is POSIX) and store hex representation of filenames as lines in the variable.
Related Questions
- → "Box: laravel/homestead-7" producing "sh.exe":box:: command not found"
- → Retrieve user's image selection from website
- → Getting error when using default task in gulp, shows the following error in Gitbash : Task requires a name that is string
- → Homestead Installaton
- → bash: homestead: command not found
- → Troubles with Artisan Tinker encoding
- → How can I access declared variable in bash when executing Laravel Envoy task?
- → coinex exchange API and use Curl /BASH to Place a market order crypto pair
- → Coiex API Curl Could not resolve host
- → How to GREP words, not lines, that contain specific characters, and print entire word
- → Cmd and Git bash have a different result when run a Python code
- → How can I convert ip ranges formatted in ip1-ip2 to cidr format?
- → Pushing to another user's remote repository without the use of pull requests