Skip to content

Instantly share code, notes, and snippets.

@jahands
Created October 13, 2025 09:48
Show Gist options
  • Select an option

  • Save jahands/1e5ad50f56f4ff405206fcf6bcbf6ac2 to your computer and use it in GitHub Desktop.

Select an option

Save jahands/1e5ad50f56f4ff405206fcf6bcbf6ac2 to your computer and use it in GitHub Desktop.
Resolve absolute path to script dir
#!/bin/sh
set -eu
# Returns the absolute directory of this script, resolving file-level symlinks.
# Usage:
# script_dir="$(get_script_dir)" || exit 1
# printf 'script_dir=%s\n' "$script_dir"
get_script_dir() {
# Ensure readlink exists (portable use; no -f).
command -v readlink >/dev/null 2>&1 || { printf '%s\n' "readlink not found" >&2; return 1; }
# 1) Seed from call path if available; else PATH
case "$0" in
*/*) script=$0 ;;
*) script=$(command -v "$0" 2>/dev/null) || { printf '%s\n' "cannot resolve: $0" >&2; return 1; } ;;
esac
case "$script" in
*/*) ;; # we have a pathname
*) printf '%s\n' "could not determine path for $0" >&2; return 1 ;;
esac
# 2) Follow file-level symlinks (guard against cycles)
max=100
while [ -L "$script" ] && [ "$max" -gt 0 ]; do
target=$(readlink "$script") || break
case "$target" in
/*) script=$target ;;
*) script="${script%/*}/$target" ;;
esac
max=$((max-1))
done
[ "$max" -eq 0 ] && { printf '%s\n' "symlink loop detected: $0" >&2; return 1; }
# 3) Canonicalize directory and print
dir=${script%/*}
script_dir=$(
CDPATH= cd -P -- "$dir" 2>/dev/null && pwd -P
) || { printf '%s\n' "failed to cd to script dir: $dir" >&2; return 1; }
printf '%s\n' "$script_dir"
}
# Example:
# script_dir="$(get_script_dir)" || exit 1
# printf 'script_dir=%s\n' "$script_dir"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment