bashのシェルスクリプトでexpand_pathとかを実装してみた
某GroovyServで欲しくなったので実装してみたんですが、こんなまどろっこしい方法しかないのでしょうかね。
どっかに素敵な車輪が転がっているのかしら。
Linuxでは普通なGNU readlinkの-f, -e, -mオプションが使えれば話は早いんですけど、Mac OS XのBSD系のreadlinkコマンドにはそんな素敵なオプションは用意されてません。
Rubyのexpand_pathとか魅力的なんですけど、できるだけ標準のシェルスクリプトの範囲で実現しておきたいわけです。
ということで、貧弱readlinkの機能範囲でパスを絶対パスに展開する関数を書いてみました。
resolve_symlink() { local TARGET=$1 # if target is symbolic link readlink $TARGET >/dev/null 2>&1 if [ $? -eq 0 ]; then local ORIGINAL_FILEPATH=`readlink $TARGET` # if original is specified as absolute path if [ $(echo $ORIGINAL_FILEPATH | cut -c 1) = "/" ]; then echo "$ORIGINAL_FILEPATH" else echo "$(dirname $TARGET)/$ORIGINAL_FILEPATH" fi else echo "$TARGET" fi } expand_path() { local TARGET=$1 if [ -d "$TARGET" ]; then echo $(cd $TARGET && pwd -P) elif [ -f "$TARGET" ]; then local TARGET_RESOLVED=$(resolve_symlink $TARGET) local FILENAME=$(basename $TARGET_RESOLVED) local DIR_EXPANDED="$(expand_path $(dirname $TARGET_RESOLVED))" echo "$DIR_EXPANDED/$FILENAME" else echo "$TARGET" fi }
とりあえず、上のコードを丸々コピーしてbashのプロンプトに貼り付けると、
$ expand_path /tmp/../tmp/hoge /private/tmp/hoge
こんな感じで相対パスだろうが、..を使ったパス記法だろうが、シンボリックリンクだろうが、実体としての絶対パスに展開されます。されるはず。のつもり。
バグ指摘、添削指導などあれば、是非お願いします。
あと、これのWindowsのBAT版とか書ける人いたら、是非ご教授願いたく。