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