For all you PHP hackers trying to write a BASH script and looking for an equivalent for PHP’s realpath function, try readlink. It can expand symbolic links and resolve relative paths like “./” and “../”. In a shell script, try this:
MY_PATH=$(readlink -f $0)
Thanks to Barry.
Pingback: CodeWord: Apokalyptik » Blog Archive » This deserves some link love
If you put quotation marks around the variable expansion you’ll be able to gracefully handle paths with spaces in them as well:
MY_PATH=$(readlink -f “$0″)
This was very appreciated for a shell script I’m building. Thank you!
saddly, readlink on Mac OS X has almost a completely different implementation and this particular method doesn’t work. sigh. still looking around….
eval “expand_tild=$inputfile”
MY_PATH=$(php -r “echo realpath(‘$expand_tild’);”)
me again, or:
#
# This function expands ~ in pathname and
# resolves the given path using perl or python or php realpath
#
function resolvepath () {
if [[ "${1}" == \~*/* || "${1}" == \~ || "${1}" == \~/* || "${1}" == \~/ ]]; then
p=”${HOME}${1:1:${#1}}”
else
p=”${1}”
fi
PYTHON_CMD=$(which python)
PERL_CMD=$(which perl)
PHP_CMD=$(which php)
if [ ! -z "${PYTHON_CMD}" ]; then
resolved_path=$(“${PYTHON_CMD}” -c ‘import os;print os.path.realpath(“‘”$p”‘”);’)
elif [ ! -z "${PERL_CMD}" ]; then
resolved_path=$(“${PERL_CMD}” -e ‘use Cwd qw(realpath);print realpath(“‘”$p”‘”);’)
elif [ ! -z "${PHP_CMD}" ]; then
resolved_path=$(“${PHP_CMD}” -r “echo realpath(‘$p’);”)
fi #linux readlink -f
}
I’m afflicted with the darwin version of readlink. For one script I needed to be able to resolve paths of directories only, and the following solution did it for me.
#!/bin/bash
dir_resolve()
{
cd “$1″ 2>/dev/null || return $? # cd to desired directory; if fail, quell any error messages but return exit status
echo “`pwd -P`” # output full, link-resolved path
}
# sample usage
if abs_path=”`dir_resolve \”$1\”`”
then
echo “$1 resolves to $abs_path”
echo pwd: `pwd` # function forks subshell, so working directory outside function is not affected
else
echo “Could not reach $1″
fi
If you simply need to return the full path of the running script and you CAN use readlink… this one-liner should work well as long as its defined at the top of the script before the inital PWD changes.
MY_PATH=$(readlink -f $(type -a $0 |awk ‘{print $3}’))
For general use, it’s probably safer to use $(readlink -m $path) for this purpose. With the -f switch the file must exist, but with -m it doesn’t matter. It depends on your purposes, but it’s good to be aware of this in any case. If I convert a path using readlink -f and then check if it’s empty, I won’t know whether it’s empty because the original path was empty, or because the file doesn’t exist.