
シナリオは次のとおりです。
foo/
> data/
> stuff/
> scripts/ -> /.../generic/scripts
任意の場所(別のフォルダまたはフォルダ内)から呼び出されたときにfoo/scripts/bar.sh
スクリプトを使用できるようにしたいですfoo/data
。foo/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