readlinkは、引数のパスがシンボリックリンクならリンク先を出力し、そうでなければ何も出力しない。
GNU readlinkの"-f"オプションはシンボリックリンクがいくつ連なってても実体のパスを出力してくれる。
MacはGNU版ではないので"-f"がない。
homebrewでcoreutilsをインストールしてreadlinkをGNU版のcoreutilsへのエイリアスにするという方法もあるみたいだけど、配布するにはつらいので、インストールしないでも良い方法を探した。
再帰的にreadlinkしているだけなので素のreadlinkを使ってシェルスクリプトで実装できるよというわけで、こういうコードが貼られていた。
#!/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
せっかくなので短くしてみた。例外処理が甘いけど元のやつもなので気にしない。
#!/bin/sh
TARGET_FILE=$1
while [ "$TARGET_FILE" != "" ]; do
cd `dirname $TARGET_FILE`
FILENAME=`basename $TARGET_FILE`
TARGET_FILE=`readlink $FILENAME`
done
echo `pwd -P`/$FILENAME
おまけ
自身の実体を出力するシェルスクリプト。
#!/bin/sh
# emulate GNU readlink's "readlink -f" behavior on Mac
# http://stackoverflow.com/questions/1055671/how-can-i-get-the-behavior-of-gnus-readlink-f-on-a-mac
function __readlink_f {
TARGET_FILE=$1
while [ "$TARGET_FILE" != "" ]; do
cd `dirname $TARGET_FILE`
FILENAME=`basename $TARGET_FILE`
TARGET_FILE=`readlink $FILENAME`
done
echo `pwd -P`/$FILENAME
}
self=`__readlink_f $0`
echo $self