I wrote a function to resolve the full path to the current Bash script, and I'm wondering if it's SOLID:
#!/usr/bin/env bash
scriptpath()
{
result=${BASH_SOURCE[0]}
# unfortunately readlink -f isn't available on Macs,
# so resolve the symlinks manually
while [ -h "$result" ]
do
symdir=$(dirname "$result")
cd -P "$symdir"
result=$(readlink "$result")
done
echo "$result"
}
echo "The path to the current script is: $(scriptpath)"
Is there anything I may have looked over in the function? I'm not sure because my answer seems quite different than the solutions listed here or here, and I'm pretty fuzzy on symlinks.
I basically want to know if my function (scriptpath
) is any different than this on a Linux system:
readlink -f "${BASH_SOURCE[0]}" | xargs -0 dirname
1 Answer 1
Let's make this testable
With a small twist, the function can become testable. Instead of finding the real path of the current script, it would be better to generalize it to find the real path of any path:
real_path()
{
result=1ドル
# ...
}
Fails to follow relative symlinks correctly
Now that the script is testable, here's a test it will not pass:
mkdir -p /tmp/a
touch /tmp/a/b
(cd /tmp/a; test -L /tmp/a/c || ln -s ../a/b c)
echo $(real_path /tmp/a/c)
The output will be ../a/b
instead of the expected /tmp/a/b
.
Basically if there are relative links in the chain of links recursively followed, the script will break.
Alternative implementation
This is what I use in production, and I haven't seen a corner case yet where it breaks:
real_path() {
target=1ドル
(
while true; do
cd "$(dirname "$target")"
target=$(basename "$target")
test -L "$target" || break
target=$(readlink "$target")
done
echo "$(pwd -P)/$target"
)
}
Notice that the portion where the function changes the working directory is wrapped within a (...)
sub-shell.
This is probably overkill,
but I think it's good to eliminate side effects as a general principle.
-L
instead of-h
in yourwhile
test as-h
has been deprecated (they want to drop it but it would break scripts so it remains for now. Probably since-h
is so commonly used for help.) \$\endgroup\$