I am trying to obtain the absolute path to the currently running script on OS X.
I saw many replies going for readlink -f $0
. However since OS X\'s
Based on the communication with commenter, I agreed that it is very hard and has no trival way to implement a realpath behaves totally same as Ubuntu.
But the following version, can handle corner cases best answer can't and satisfy my daily needs on macbook. Put this code into your ~/.bashrc and remember:
# 1. if is a dir, try cd and pwd
# 2. if is a file, try cd its parent and concat dir+file
realpath() {
[ "$1" = "" ] && return 1
dir=`dirname "$1"`
file=`basename "$1"`
last=`pwd`
[ -d "$dir" ] && cd $dir || return 1
if [ -d "$file" ];
then
# case 1
cd $file && pwd || return 1
else
# case 2
echo `pwd`/$file | sed 's/\/\//\//g'
fi
cd $last
}
Use Python to get it:
#!/usr/bin/env python
import os
import sys
print(os.path.realpath(sys.argv[1]))
I was looking for a solution for use in a system provision script, i.e., run before Homebrew is even installed. Lacking a proper solution I'd just offload the task to a cross-platform language, e.g., Perl:
script_abspath=$(perl -e 'use Cwd "abs_path"; print abs_path(@ARGV[0])' -- "$0")
More often what we actually want is the containing directory:
here=$(perl -e 'use File::Basename; use Cwd "abs_path"; print dirname(abs_path(@ARGV[0]));' -- "$0")
realpath for Mac OS X
realpath() {
path=`eval echo "$1"`
folder=$(dirname "$path")
echo $(cd "$folder"; pwd)/$(basename "$path");
}
Example with related path:
realpath "../scripts/test.sh"
Example with home folder
realpath "~/Test/../Test/scripts/test.sh"
These three simple steps are going to solve this and many other OS X issues:
brew install coreutils
grealpath .
(3) may be changed to just realpath
, see (2) output
Ugh. I found the prior answers a bit wanting for a few reasons: in particular, they don't resolve multiple levels of symbolic links, and they are extremely "Bash-y". While the original question does explicitly ask for a "Bash script", it also makes mention of Mac OS X's BSD-like, non-GNU readlink
. So here's an attempt at some reasonable portability (I've checked it with bash as 'sh' and dash), resolving an arbitrary number of symbolic links; and it should also work with whitespace in the path(s), although I'm not sure of the behavior if there is white space the base name of the utility itself, so maybe, um, avoid that?
#!/bin/sh
realpath() {
OURPWD=$PWD
cd "$(dirname "$1")"
LINK=$(readlink "$(basename "$1")")
while [ "$LINK" ]; do
cd "$(dirname "$LINK")"
LINK=$(readlink "$(basename "$1")")
done
REALPATH="$PWD/$(basename "$1")"
cd "$OURPWD"
echo "$REALPATH"
}
realpath "$@"
Hope that can be of some use to someone.