realpath.bash raw

   1  #!/usr/bin/env bash
   2  
   3  # Based on realpath.sh written by Michael Kropat
   4  # Found at: https://github.com/mkropat/sh-realpath/blob/65512368b8155b176b67122aa395ac580d9acc5b/realpath.sh
   5  
   6  bash_realpath() {
   7      canonicalize_path "$(resolve_symlinks "$1")"
   8  }
   9  
  10  resolve_symlinks() {
  11      _resolve_symlinks "$1"
  12  }
  13  
  14  _resolve_symlinks() {
  15      _assert_no_path_cycles "$@" || return
  16  
  17      local dir_context path
  18      if path=$(readlink -- "$1"); then
  19          dir_context=$(dirname -- "$1")
  20          _resolve_symlinks "$(_prepend_dir_context_if_necessary "$dir_context" "$path")" "$@"
  21      else
  22          printf '%s\n' "$1"
  23      fi
  24  }
  25  
  26  _prepend_dir_context_if_necessary() {
  27      if [ "$1" = . ]; then
  28          printf '%s\n' "$2"
  29      else
  30          _prepend_path_if_relative "$1" "$2"
  31      fi
  32  }
  33  
  34  _prepend_path_if_relative() {
  35      case "$2" in
  36          /* ) printf '%s\n' "$2" ;;
  37           * ) printf '%s\n' "$1/$2" ;;
  38      esac
  39  }
  40  
  41  _assert_no_path_cycles() {
  42      local target path
  43  
  44      target=$1
  45      shift
  46  
  47      for path in "$@"; do
  48          if [ "$path" = "$target" ]; then
  49              return 1
  50          fi
  51      done
  52  }
  53  
  54  canonicalize_path() {
  55      if [ -d "$1" ]; then
  56          _canonicalize_dir_path "$1"
  57      else
  58          _canonicalize_file_path "$1"
  59      fi
  60  }
  61  
  62  _canonicalize_dir_path() {
  63      (cd "$1" 2>/dev/null && pwd -P)
  64  }
  65  
  66  _canonicalize_file_path() {
  67      local dir file
  68      dir=$(dirname -- "$1")
  69      file=$(basename -- "$1")
  70      (cd "$dir" 2>/dev/null && printf '%s/%s\n' "$(pwd -P)" "$file")
  71  }
  72