絶対ディレクトリを探す

絶対ディレクトリを探す

シナリオは次のとおりです。

foo/
> data/
> stuff/
> scripts/ -> /.../generic/scripts

任意の場所(別のフォルダまたはフォルダ内)から呼び出されたときにfoo/scripts/bar.shスクリプトを使用できるようにしたいですfoo/datafoo/stuff

しかし、ちょうど使用すると、foo_dir='dirname $0'/..シンボリックリンクが指すディレクトリに移動します! (そしてgeneric代わりに入手してくださいfoo!)

一部のパターンを使用して最後を食べると、$0ディレクトリ内でスクリプトを呼び出すことができるため、機能しません。

だから結局私が見つけた唯一のことは、次のような非常に醜いものでした。

dir=`dirname $0`
cd $dir
dir=`pwd | sed -r 's_/[^/]+$__'`
cd -

...しかし、もっと良い方法があると確信しています。

私が使用するもの:

dir=$( dirname $( cd `dirname $0`; pwd ) )

完璧かどうかはわかりませんが、期待したほどの性能を発揮するようです。

答え1

次の1行を使用できます。

DIR="$(cd "$( dirname "$0" )" && pwd )"

答え2

初めて質問をもっと読むことができず、申し訳ありません。

変える:

foo_dir = $(dirname $0)/..

どうですか?

foo_dir = $(dirname $(dirname $0))

ただし、これは$ 0に少なくとも1つのディレクトリコンポーネントがある場合にのみ機能します。この保証はありますか?

答え3

はい、..シンボリックリンクの存在は実際の問題です。ロブパイクが書いた。このトピックに関する全論文

絶対パス名を..使用しないことをお勧めします。dirname

case $0 in
  /*) where="$0" ;;
  *)  where="$(pwd)/$0" ;;
esac
# postcondition: $where is an absolute pathname for script
# N.B $where = .../foo/scripts/command

base="$(dirname "$(dirname "$where")")"
# postcondition: $base = .../foo

resource="$base/data"

私は実際に最初のイディオム(可能な相対パス名から絶対パス名を復元すること)を使用しており、~/bin特にこの目的のために私のディレクトリにスクリプトがあります。

絶対パス名を処理すると、dirname状況は賢明に機能します。

答え4

あなたの投稿はやや横説説であり、いくつかの声明は矛盾しているように見えますが、私が正しく理解した場合は、フォームがあり、その$0部分をfoo/scripts/bar.sh抽出しようとしていますfoo。また、パスに常に少なくとも2つのディレクトリがあることを保証することもできます(もしそれだけを持っていればbar.sh問題になります)。その後、パスの最後の2つのコンポーネントを削除できます。

DIR=${0%/*/*}

ただし、スクリプトを呼び出すことでこれを行うことができます。scripts/bar.shこの場合、単純なパターン置換は機能しません。合格は言うまでもなく、$PATH条件付きにすることもできます。

case $0 in
  */*/*) DIR=${0%/*/*};;
  ?*/*) DIR=.;;
  /*) echo 1>&2 "Storing $0 in the root directory is not supported, aborting."
      exit 125;;
  *) # The script was called through the `PATH`
    IFS=:; set -f; unset DIR
    for d in $PATH; do
      if [ -x "$d/$0" ]; then
        # If you put relative directories in your PATH, you get what you deserve.
        DIR=${d%/*};;
      fi
    done
    if [ -z "$DIR" ]; then
      echo 1>&2 "$0: Fatal error: I can't find myself."
      exit 125
    fi
    unset IFS; set +f;;
esac

関連情報