Hayao0819
@Hayao0819 (山田 ハヤオ)

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

シェルスクリプトでスクリプトのディレクトリの絶対パスを取得する方法

概要

シェルスクリプトでスクリプトが置かれている絶対パスを取得し、それを変数に代入して使用する際に、どのようにパスを取得するのが良いのでしょうか?また、皆さんが使っている方法を教えてほしいです。

方法

#!/usr/bin/env bash

script_path=(
    "$(dirname "$(realpath "${0}")")"
    "$(cd "$(dirname "${0}")"; pwd)"
    "$(readlink -f "${0}")"
    "$( cd -P "$( dirname "$(readlink -f "${0}")" )" && pwd )"
)

printf "%s\n" "${script_path[@]}"

dirname "$(realpath "${0}")"

自分で考えました。これが一番シンプルな気がするのですがなにか正常に動作しない場合などがあるのでしょうか?

cd "$(dirname "${0}")"; pwd

ネットで検索するとだいたいこれが見つかります。わざわざcdしてpwdするのって面倒だと思うんですが、なにか利点があるのでしょうか?

readlink -f "${0}"

とあるOSSで使用されていた方法です。どうやらbashコマンドの引数として実行するとファイル名まで含まれてしまうそうです。

cd -P "$( dirname "$(readlink -f "${0}")" )" && pwd

上記のOSSで現在使用されている方法です。上の方法からファイル名を除外します。
わざわざdirnameで取得してからpwdする意味がわかりません。

参考

0

realpathってたしかmacだと標準で入ってなくて、ちょっと前にそれで引っかかりましたね。
CI(GitHub Actions)だったので適当にbrew install coreutilsするステップ入れて解決しましたが

0Like

コマンドとしてrealpathが存在しない確率とdirnameが存在しない確率を考えると…。
圧倒的に後者が存在する確率が高いから、よく使われてるのではないかと。

あ、1番目はdirnameも使ってますね

0Like

前に https://github.com/ko1nksm/readlinkf というのを作りました。これは readlink -f "${0}" 相当(GNU readlink -f と完全互換)ですが POSIX 準拠の機能だけを使って作ったシェル関数なので bash 以外(例えば dash や zsh)でも macOS でも realpathreadlink が入ってない環境でも動きます。dirname など外部コマンドも使用してないの外部コマンドを極力使わないようにしてる(lsのみ)ので速いです。

あとはこれでスクリプトの絶対パスを取得してからディレクトリのみを取り出します。具体的には以下のとおりです。 変数展開を使っているのはもちろん速いからです。

self_path=$(readlinkf "$0")
base_dir=${self_path%/*}

readlinkf は ライセンスを Creative Commons Zero v1.0 Universal にして著作権を放棄しているので自由に自分のスクリプトに組み込んで使えます。著作者情報の明記も不要です。

1Like

Your answer might help someone💌