← retour aux snippets

bash: chemin du script courant fiable

Obtenir le dossier du script (résolution de symlinks) pour charger des fichiers voisins en toute sécurité.


objectif

Récupérer le chemin absolu du script Bash, même lancé depuis un autre dossier et même si le script est un symlink. Utile pour charger des ressources relatives (configs, templates) ou positionner la racine de projet.

code minimal

#!/usr/bin/env bash
set -Eeuo pipefail

get_script_dir() {
  local src="${BASH_SOURCE[0]}"
  while [ -h "$src" ]; do
    local dir
    dir="$(cd -P "$(dirname "$src")" && pwd)"
    src="$(readlink "$src")"
    [[ "$src" != /* ]] && src="$dir/$src"
  done
  cd -P "$(dirname "$src")" && pwd
}

SCRIPT_DIR="$(get_script_dir)"
echo "script dir: $SCRIPT_DIR"

utilisation

# accéder à un fichier voisin quel que soit le dossier courant
CONFIG="$SCRIPT_DIR/config/app.conf"
[ -r "$CONFIG" ] || { echo "config introuvable: $CONFIG" >&2; exit 1; }

# positionner la racine du projet et exécuter une commande
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
(cd "$PROJECT_ROOT" && make -s build)

# sourcer des utilitaires à côté du script
. "$SCRIPT_DIR/lib.sh"

# écrire un fichier de sortie à côté du script (écriture atomique)
tmp="$(mktemp -p "$SCRIPT_DIR" .out.XXXXXX)"
generate_content > "$tmp" && mv -f "$tmp" "$SCRIPT_DIR/output.txt"

variante(s) utile(s)

# utiliser realpath si disponible (plus simple)
if command -v realpath >/dev/null 2>&1; then
  SCRIPT_DIR="$(dirname "$(realpath "${BASH_SOURCE[0]}")")"
fi

# détecter si le script est exécuté directement ou sourcé
if [ "${BASH_SOURCE[0]}" = "$0" ]; then
  echo "exécuté: $0"
else
  echo "sourcé depuis: $0"
fi

# fallback POSIX (moins robuste: ne suit pas les symlinks complexes)
POSIX_DIR="$(cd "$(dirname "$0")" && pwd)"
echo "posix dir (approx): $POSIX_DIR"

notes

  • fonctionne en Bash (Linux/macOS). Évitez readlink -f qui n’existe pas sur macOS.
  • renvoie un chemin absolu et canonique (cd -P suit les dossiers réels).
  • ${BASH_SOURCE[0]} pointe vers le fichier courant même quand le script est sourcé.
  • pour zsh, utilisez ${(%):-%N} à la place de ${BASH_SOURCE[0]} si nécessaire.