Friday, June 13, 2014

Getting absolute path in Bash in OSX

The equivalent of "readlink -f" in OSX? None. At least not without installing GNU Coreutils or some bash-fu.

Am I cute, or am I cute?

GNU Coretutils

My recommendation is: just use coretutils and forget about all the complication. You can install Homebrew, and readlink is conveniently available as greadlink, so any scripts that depend on the original readlink in OSX are not affected.
coreutils using

Bash Function

If you cannot install or use GNU coreutils, you will have to resort to writing a bash function.


#!/bin/bash

realpath() {
    [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}"
}

realpath "$0"


This is a better solution, but be aware of the limitation that it does not detect recursive links and handle errors.


#!/bin/sh

TARGET_FILE=$1

cd `dirname $TARGET_FILE`
TARGET_FILE=`basename $TARGET_FILE`

# Iterate down a (possible) chain of symlinks
while [ -L "$TARGET_FILE" ]
do
    TARGET_FILE=`readlink $TARGET_FILE`
    cd `dirname $TARGET_FILE`
    TARGET_FILE=`basename $TARGET_FILE`
done

# Compute the canonicalized name by finding the physical path 
# for the directory we're in and appending the target file.
PHYS_DIR=`pwd -P`
RESULT=$PHYS_DIR/$TARGET_FILE
echo $RESULT



This is a simpler alternative, but does not work if symlink is something like /usr/bin/


function readlink() {
  DIR=$(echo "${1%/*}")
  (cd "$DIR" && echo "$(pwd -P)")
}


Use Python

You can use python's abspath


#!/usr/bin/env python
import os.path
import sys

for arg in sys.argv[1:]:
    print os.path.abspath(arg)




Don't Use Readlink

This is the solution I am using now - the bash script is part of a package's cross-compilation script. Since I know there is no fancy linking shtick involved in my situation, removing "readlink -f" works perfectly.


No comments:

Post a Comment