スクリプト自体内から Bash スクリプトのソース ディレクトリを取得します

StackOverflow https://stackoverflow.com/questions/59895

  •  09-06-2019
  •  | 
  •  

質問

が保存されているディレクトリのパスを取得するにはどうすればよいですか? バッシュ スクリプトが見つかった場合、 内部 そのスクリプト?

たとえば、Bash スクリプトを別のアプリケーションのランチャーとして使用したいとします。次のように、作業ディレクトリを Bash スクリプトが配置されているディレクトリに変更して、そのディレクトリ内のファイルを操作できるようにしたいと考えています。

$ ./application
役に立ちましたか?

解決

#!/bin/bash

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"

これは、どこから呼び出されているかに関係なく、スクリプトの完全なディレクトリ名を表示する便利なワンライナーです。

これは、スクリプトの検索に使用されるパスの最後のコンポーネントがシンボリックリンクでない限り機能します (ディレクトリ リンクは問題ありません)。スクリプト自体へのリンクも解決したい場合は、複数行のソリューションが必要です。

#!/bin/bash

SOURCE="${BASH_SOURCE[0]}"
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
  DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )"
  SOURCE="$(readlink "$SOURCE")"
  [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
done
DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )"

この最後のものは、エイリアスの任意の組み合わせで機能します。 source, bash -c, 、シンボリックリンクなど。

注意してください:もし、あんたが cd このスニペットを実行する前に別のディレクトリに移動すると、結果が正しくなくなる可能性があります。

また、次のことに注意してください $CDPATH 落とし穴, 、およびユーザーが cd を賢くオーバーライドして出力を stderr にリダイレクトした場合の stderr 出力の副作用 (呼び出し時などのエスケープ シーケンスを含む) update_terminal_cwd >&2 Mac の場合)。追加 >/dev/null 2>&1 あなたの終わりに cd コマンドは両方の可能性を処理します。

どのように機能するかを理解するには、次のより詳細なフォームを実行してみてください。

#!/bin/bash

SOURCE="${BASH_SOURCE[0]}"
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
  TARGET="$(readlink "$SOURCE")"
  if [[ $TARGET == /* ]]; then
    echo "SOURCE '$SOURCE' is an absolute symlink to '$TARGET'"
    SOURCE="$TARGET"
  else
    DIR="$( dirname "$SOURCE" )"
    echo "SOURCE '$SOURCE' is a relative symlink to '$TARGET' (relative to '$DIR')"
    SOURCE="$DIR/$TARGET" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
  fi
done
echo "SOURCE is '$SOURCE'"
RDIR="$( dirname "$SOURCE" )"
DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )"
if [ "$DIR" != "$RDIR" ]; then
  echo "DIR '$RDIR' resolves to '$DIR'"
fi
echo "DIR is '$DIR'"

そして、次のようなものが出力されます:

SOURCE './scriptdir.sh' is a relative symlink to 'sym2/scriptdir.sh' (relative to '.')
SOURCE is './sym2/scriptdir.sh'
DIR './sym2' resolves to '/home/ubuntu/dotfiles/fo fo/real/real1/real2'
DIR is '/home/ubuntu/dotfiles/fo fo/real/real1/real2'

他のヒント

使用 dirname "$0":

#!/bin/bash
echo "The script you are running has basename `basename "$0"`, dirname `dirname "$0"`"
echo "The present working directory is `pwd`"

を使用して pwd スクリプトが含まれているディレクトリからスクリプトを実行していない場合、単独では機能しません。

[matt@server1 ~]$ pwd
/home/matt
[matt@server1 ~]$ ./test2.sh
The script you are running has basename test2.sh, dirname .
The present working directory is /home/matt
[matt@server1 ~]$ cd /tmp
[matt@server1 tmp]$ ~/test2.sh
The script you are running has basename test2.sh, dirname /home/matt
The present working directory is /tmp

dirname コマンドは最も基本的なもので、$0 (スクリプト名) 変数からファイル名までのパスを単純に解析します。

dirname "$0"

しかし、として マットB 指摘されているように、返されるパスはスクリプトの呼び出し方法によって異なります。pwd は、スクリプトが存在するディレクトリではなく、現在のディレクトリが何であるかを示すだけであるため、その仕事をしません。さらに、スクリプトへのシンボリック リンクが実行されると、実際のスクリプトではなく、リンクが存在する場所への (おそらく相対) パスが取得されます。

他の人も言及しました 読むリンク コマンドを使用しますが、最も簡単には次のコマンドを使用できます。

dirname "$(readlink -f "$0")"

readlink は、スクリプト パスをファイル システムのルートからの絶対パスに解決します。したがって、単一または二重ドット、チルダ、シンボリック リンクを含むパスは完全なパスに解決されます。

これらのそれぞれを示すスクリプトは次のとおりです。 whatdir.sh:

#!/bin/bash
echo "pwd: `pwd`"
echo "\$0: $0"
echo "basename: `basename $0`"
echo "dirname: `dirname $0`"
echo "dirname/readlink: $(dirname $(readlink -f $0))"

相対パスを使用して、ホーム ディレクトリでこのスクリプトを実行します。

>>>$ ./whatdir.sh 
pwd: /Users/phatblat
$0: ./whatdir.sh
basename: whatdir.sh
dirname: .
dirname/readlink: /Users/phatblat

繰り返しますが、スクリプトへのフルパスを使用します。

>>>$ /Users/phatblat/whatdir.sh 
pwd: /Users/phatblat
$0: /Users/phatblat/whatdir.sh
basename: whatdir.sh
dirname: /Users/phatblat
dirname/readlink: /Users/phatblat

ディレクトリを変更しています:

>>>$ cd /tmp
>>>$ ~/whatdir.sh 
pwd: /tmp
$0: /Users/phatblat/whatdir.sh
basename: whatdir.sh
dirname: /Users/phatblat
dirname/readlink: /Users/phatblat

最後にシンボリック リンクを使用してスクリプトを実行します。

>>>$ ln -s ~/whatdir.sh whatdirlink.sh
>>>$ ./whatdirlink.sh 
pwd: /tmp
$0: ./whatdirlink.sh
basename: whatdirlink.sh
dirname: .
dirname/readlink: /Users/phatblat
pushd . > /dev/null
SCRIPT_PATH="${BASH_SOURCE[0]}"
if ([ -h "${SCRIPT_PATH}" ]); then
  while([ -h "${SCRIPT_PATH}" ]); do cd `dirname "$SCRIPT_PATH"`; 
  SCRIPT_PATH=`readlink "${SCRIPT_PATH}"`; done
fi
cd `dirname ${SCRIPT_PATH}` > /dev/null
SCRIPT_PATH=`pwd`;
popd  > /dev/null

すべてのバージョンで動作します。

  • 複数の深さのソフトリンク経由で呼び出された場合、
  • ファイルするとき
  • スクリプトがコマンドによって呼び出されたときsource「別名 . (ドット) 演算子。
  • 引数のとき $0 呼び出し元から変更されます。
  • "./script"
  • "/full/path/to/script"
  • "/some/path/../../another/path/script"
  • "./some/folder/script"

あるいは、bash スクリプト自体が 相対シンボリックリンク あなた 欲しい これをたどって、リンク先のスクリプトのフルパスを返します。

pushd . > /dev/null
SCRIPT_PATH="${BASH_SOURCE[0]}";
if ([ -h "${SCRIPT_PATH}" ]) then
  while([ -h "${SCRIPT_PATH}" ]) do cd `dirname "$SCRIPT_PATH"`; SCRIPT_PATH=`readlink "${SCRIPT_PATH}"`; done
fi
cd `dirname ${SCRIPT_PATH}` > /dev/null
SCRIPT_PATH=`pwd`;
popd  > /dev/null

SCRIPT_PATH 呼び出し方法に関係なく、フルパスで指定されます。
これがスクリプトの先頭にあることを確認してください。

このコメントとコードはコピーレフトであり、GPL2.0 以降または CC-SA 3.0 (CreativeCommons Share Alike) 以降に基づく選択可能なライセンスです。(c) 2008。無断転載を禁じます。いかなる種類の保証もありません。あなたは警告を受けました。
http://www.gnu.org/licenses/gpl-2.0.txt
http://creativecommons.org/licenses/by-sa/3.0/
18eedfe1c99df68dc94d4a94712a71aaa8e1e9e36cacf421b9463dd2bbaa02906d0d6656

短い答え:

`dirname $0`

または (できれば):

$(dirname "$0")

$BASH_SOURCE を使用できます

#!/bin/bash

scriptdir=`dirname "$BASH_SOURCE"`

これは bash 拡張機能であるため、#!/bin/sh ではなく #!/bin/bash を使用する必要があることに注意してください。

これで済むはずです:

DIR=$(dirname "$(readlink -f "$0")")

パス内のシンボリックリンクとスペースを処理します。マニュアルページを参照してください 姓名 そして 読むリンク.

編集:

コメントトラックによると、Mac OS では動作しないようです。それがなぜなのかは分かりません。助言がありますか?

pwd 現在の作業ディレクトリを見つけるために使用できます。 dirname 特定のファイルのディレクトリを検索します (実行されたコマンドは $0, 、 それで dirname $0 現在のスクリプトのディレクトリが表示されるはずです)。

しかし、 dirname ファイル名のディレクトリ部分を正確に示します。これは、現在の作業ディレクトリを基準にしたものである可能性が高くなります。スクリプトが何らかの理由でディレクトリを変更する必要がある場合、次の出力が dirname 意味がなくなってしまいます。

私は次のことを提案します。

#!/bin/bash

reldir=`dirname $0`
cd $reldir
directory=`pwd`

echo "Directory is $directory"

このようにして、相対ディレクトリではなく絶対ディレクトリを取得します。

スクリプトは別の bash インスタンスで実行されるため、後で作業ディレクトリを復元する必要はありませんが、何らかの理由でスクリプトを元に戻したい場合は、次の値を簡単に割り当てることができます。 pwd 将来の使用のために、ディレクトリを変更する前に変数に保存します。

ただではあるが

cd `dirname $0`

質問内の特定のシナリオを解決するには、絶対パスを持っている方が一般的により便利だと思います。

これは他の人が言っているほど簡単ではないと思います。現在のディレクトリが必ずしもスクリプトのあるディレクトリであるとは限らないため、pwd は機能しません。$0 にも常に情報があるとは限りません。スクリプトを呼び出す次の 3 つの方法を検討してください。

./script

/usr/bin/script

script

1 番目と 3 番目の方法では、$0 には完全なパス情報がありません。2 番目と 3 番目では、pwd は機能しません。3 番目の方法でディレクトリを取得する唯一の方法は、パスを実行して、正しく一致するファイルを見つけることです。基本的に、コードは OS の動作をやり直す必要があります。

あなたが求めていることを行う1つの方法は、/usr/shareディレクトリ内のデータをハードコーディングし、フルパスで参照することです。いずれにせよ、データは /usr/bin ディレクトリにあるべきではないので、おそらくこれがすべきことです。

SCRIPT_DIR=$( cd ${0%/*} && pwd -P )

これにより、Mac OS X 10.6.6 上の現在の作業ディレクトリが取得されます。

DIR=$(cd "$(dirname "$0")"; pwd)
$(dirname "$(readlink -f "$BASH_SOURCE")")

何度もこのページに来て、受け入れられた回答のワンライナーをコピーペーストするのにうんざりしています。問題は、理解したり覚えたりするのが簡単ではないことです。

覚えやすいスクリプトを次に示します。

DIR=$(dirname "${BASH_SOURCE[0]}")  # get the directory name
DIR=$(realpath "${DIR}")    # resolve its full path if need be

これは Linux 固有ですが、以下を使用できます。

SELF=$(readlink /proc/$$/fd/255)

以下は POSIX 準拠のワンライナーです。

SCRIPT_PATH=`dirname "$0"`; SCRIPT_PATH=`eval "cd \"$SCRIPT_PATH\" && pwd"`

# test
echo $SCRIPT_PATH

これらをすべて試しましたが、どれも機能しませんでした。1 つは非常に近くにありましたが、小さなバグがあり、ひどく壊れていました。パスを引用符で囲むのを忘れていました。

また、多くの人はシェルからスクリプトを実行していると想定しているため、新しいスクリプトを開くとデフォルトでホームに設定されることを忘れています。

このディレクトリのサイズを試してみます。

/var/誰も/考えなかった/存在するスペースについて/ディレクトリ内/名前/そしてこれがあなたのファイルです。テキスト

これにより、実行方法や場所に関係なく、正しく実行されます。

#!/bin/bash
echo "pwd: `pwd`"
echo "\$0: $0"
echo "basename: `basename "$0"`"
echo "dirname: `dirname "$0"`"

実際に便利にするために、実行中のスクリプトのディレクトリに変更する方法を次に示します。

cd "`dirname "$0"`"

お役に立てば幸いです

簡単で正しい方法は次のとおりです。

actual_path=$(readlink -f "${BASH_SOURCE[0]}")
script_dir=$(dirname "$actual_path")

説明:

  • ${BASH_SOURCE[0]} - スクリプトへのフルパス。この値は、スクリプトがソースされている場合でも正しくなります。 source <(echo 'echo $0') プリント バッシュ, と置き換えながら、 ${BASH_SOURCE[0]} スクリプトのフルパスを出力します。(もちろん、これは Bash に依存しても問題がないことを前提としています。)

  • readlink -f - 指定されたパス内のシンボリックリンクを再帰的に解決します。これは GNU 拡張機能であり、(たとえば) BSD システムでは利用できません。Mac を実行している場合は、Homebrew を使用して GNU をインストールできます coreutils これを次のものに置き換えます greadlink -f.

  • そしてもちろん dirname パスの親ディレクトリを取得します。

私なら次のようなものを使います:

# retrieve the full pathname of the called script
scriptPath=$(which $0)

# check whether the path is a link or not
if [ -L $scriptPath ]; then

    # it is a link then retrieve the target path and get the directory name
    sourceDir=$(dirname $(readlink -f $scriptPath))

else

    # otherwise just get the directory name of the script path
    sourceDir=$(dirname $scriptPath)

fi

で指摘されたソリューション e-satis と 3bcdnlklvc04a のわずかな改訂 彼らの答え

SCRIPT_DIR=''
pushd "$(dirname "$(readlink -f "$BASH_SOURCE")")" > /dev/null && {
    SCRIPT_DIR="$PWD"
    popd > /dev/null
}    

これは、リストされているすべてのケースで引き続き機能するはずです。

編集:konsoleboxのおかげで、pushdに失敗した後のpopdを防止します

#!/bin/sh
PRG="$0"

# need this for relative symlinks
while [ -h "$PRG" ] ; do
   PRG=`readlink "$PRG"`
done

scriptdir=`dirname "$PRG"`

$_ $0 の代替品として言及する価値があります。bash からスクリプトを実行している場合、受け入れられた回答は次のように短縮できます。

DIR="$( dirname "$_" )"

これはスクリプトの最初のステートメントである必要があることに注意してください。

与えられた回答の多くを比較し、よりコンパクトな解決策をいくつか考え出しました。これらは、次のお気に入りの組み合わせから生じるクレイジーなエッジ ケースをすべて処理できるようです。

  • 絶対パスまたは相対パス
  • ファイルとディレクトリのソフトリンク
  • として呼び出し script, bash script, bash -c script, source script, 、 または . script
  • スペース、タブ、改行、Unicode など。ディレクトリおよび/またはファイル名内
  • ハイフンで始まるファイル名

Linux から実行している場合は、 proc ハンドルは、現在実行中のスクリプトの完全に解決されたソースを見つけるための最良のソリューションです (対話型セッションでは、リンクはそれぞれのソースを指します) /dev/pts/X):

resolved="$(readlink /proc/$$/fd/255 && echo X)" && resolved="${resolved%$'\nX'}"

これには少し醜い点がありますが、修正はコンパクトで理解しやすいものです。bash プリミティブのみを使用しているわけではありませんが、それで問題ありません。 readlink タスクが大幅に簡素化されます。の echo X を追加します X ファイル名の末尾の空白が食い込まれないように、変数文字列の末尾に追加され、パラメータ置換が行われます。 ${VAR%X} 行の最後で、 X. 。なぜなら readlink 独自の改行が追加されます (前のトリックがなければ、通常はコマンド置換で使用されてしまいます)。これも削除する必要があります。これは、次を使用するのが最も簡単です。 $'' 引用符スキーム。これにより、次のようなエスケープ シーケンスを使用できます。 \n 改行を表すために使用します (これは、不正な名前のディレクトリやファイルを簡単に作成する方法でもあります)。

上記は、Linux 上で現在実行中のスクリプトを見つけるためのニーズをカバーしていますが、 proc ファイルシステムを自由に使用できる場合、または他のファイルの完全に解決されたパスを見つけようとしている場合は、以下のコードが役に立つかもしれません。上記のワンライナーを少し変更しただけです。奇妙なディレクトリ/ファイル名をいじっている場合は、両方のファイル名で出力を確認してください。 ls そして readlink 有益です。 ls 「簡略化された」パスを出力します。 ? 改行などの場合。

absolute_path=$(readlink -e -- "${BASH_SOURCE[0]}" && echo x) && absolute_path=${absolute_path%?x}
dir=$(dirname -- "$absolute_path" && echo x) && dir=${dir%?x}
file=$(basename -- "$absolute_path" && echo x) && file=${file%?x}

ls -l -- "$dir/$file"
printf '$absolute_path: "%s"\n' "$absolute_path"

使ってみてください:

real=$(realpath $(dirname $0))

GNU coreutils readlink を備えたシステムの場合 (例:Linux):

$(readlink -f "$(dirname "$0")")

使用する必要はありません BASH_SOURCE いつ $0 スクリプトのファイル名が含まれます。

それで...これは持っていると思います。パーティーに遅れましたが、このスレッドに出会った人はここにいることに感謝する人もいると思います。コメントで説明する必要があります。

#!/bin/sh # dash bash ksh # !zsh (issues). G. Nixon, 12/2013. Public domain.

## 'linkread' or 'fullpath' or (you choose) is a little tool to recursively
## dereference symbolic links (ala 'readlink') until the originating file
## is found. This is effectively the same function provided in stdlib.h as
## 'realpath' and on the command line in GNU 'readlink -f'.

## Neither of these tools, however, are particularly accessible on the many
## systems that do not have the GNU implementation of readlink, nor ship
## with a system compiler (not to mention the requisite knowledge of C).

## This script is written with portability and (to the extent possible, speed)
## in mind, hence the use of printf for echo and case statements where they
## can be substituded for test, though I've had to scale back a bit on that.

## It is (to the best of my knowledge) written in standard POSIX shell, and
## has been tested with bash-as-bin-sh, dash, and ksh93. zsh seems to have
## issues with it, though I'm not sure why; so probably best to avoid for now.

## Particularly useful (in fact, the reason I wrote this) is the fact that
## it can be used within a shell script to find the path of the script itself.
## (I am sure the shell knows this already; but most likely for the sake of
## security it is not made readily available. The implementation of "$0"
## specificies that the $0 must be the location of **last** symbolic link in
## a chain, or wherever it resides in the path.) This can be used for some
## ...interesting things, like self-duplicating and self-modifiying scripts.

## Currently supported are three errors: whether the file specified exists
## (ala ENOENT), whether its target exists/is accessible; and the special
## case of when a sybolic link references itself "foo -> foo": a common error
## for beginners, since 'ln' does not produce an error if the order of link
## and target are reversed on the command line. (See POSIX signal ELOOP.)

## It would probably be rather simple to write to use this as a basis for
## a pure shell implementation of the 'symlinks' util included with Linux.

## As an aside, the amount of code below **completely** belies the amount
## effort it took to get this right -- but I guess that's coding for you.

##===-------------------------------------------------------------------===##

for argv; do :; done # Last parameter on command line, for options parsing.

## Error messages. Use functions so that we can sub in when the error occurs.

recurses(){ printf "Self-referential:\n\t$argv ->\n\t$argv\n" ;}
dangling(){ printf "Broken symlink:\n\t$argv ->\n\t"$(readlink "$argv")"\n" ;}
errnoent(){ printf "No such file: "$@"\n" ;} # Borrow a horrible signal name.

# Probably best not to install as 'pathfull', if you can avoid it.

pathfull(){ cd "$(dirname "$@")"; link="$(readlink "$(basename "$@")")"

## 'test and 'ls' report different status for bad symlinks, so we use this.

 if [ ! -e "$@" ]; then if $(ls -d "$@" 2>/dev/null) 2>/dev/null;  then
    errnoent 1>&2; exit 1; elif [ ! -e "$@" -a "$link" = "$@" ];   then
    recurses 1>&2; exit 1; elif [ ! -e "$@" ] && [ ! -z "$link" ]; then
    dangling 1>&2; exit 1; fi
 fi

## Not a link, but there might be one in the path, so 'cd' and 'pwd'.

 if [ -z "$link" ]; then if [ "$(dirname "$@" | cut -c1)" = '/' ]; then
   printf "$@\n"; exit 0; else printf "$(pwd)/$(basename "$@")\n"; fi; exit 0
 fi

## Walk the symlinks back to the origin. Calls itself recursivly as needed.

 while [ "$link" ]; do
   cd "$(dirname "$link")"; newlink="$(readlink "$(basename "$link")")"
   case "$newlink" in
    "$link") dangling 1>&2 && exit 1                                       ;;
         '') printf "$(pwd)/$(basename "$link")\n"; exit 0                 ;;
          *) link="$newlink" && pathfull "$link"                           ;;
   esac
 done
 printf "$(pwd)/$(basename "$newlink")\n"
}

## Demo. Install somewhere deep in the filesystem, then symlink somewhere 
## else, symlink again (maybe with a different name) elsewhere, and link
## back into the directory you started in (or something.) The absolute path
## of the script will always be reported in the usage, along with "$0".

if [ -z "$argv" ]; then scriptname="$(pathfull "$0")"

# Yay ANSI l33t codes! Fancy.
 printf "\n\033[3mfrom/as: \033[4m$0\033[0m\n\n\033[1mUSAGE:\033[0m   "
 printf "\033[4m$scriptname\033[24m [ link | file | dir ]\n\n         "
 printf "Recursive readlink for the authoritative file, symlink after "
 printf "symlink.\n\n\n         \033[4m$scriptname\033[24m\n\n        "
 printf " From within an invocation of a script, locate the script's "
 printf "own file\n         (no matter where it has been linked or "
 printf "from where it is being called).\n\n"

else pathfull "$@"
fi

次の相互互換性のあるソリューションを試してください。

CWD="$(cd -P -- "$(dirname -- "$0")" && pwd -P)"

として realpath または readlink コマンドは常に使用できるわけではありません (オペレーティング システムによって異なります)。 ${BASH_SOURCE[0]} bash シェルでのみ使用できます。

あるいは、bash で次の関数を試すこともできます。

realpath () {
  [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}"
}

この関数は 1 つの引数を取ります。引数がすでに絶対パスを持っている場合はそのまま出力し、それ以外の場合は出力します。 $PWD 変数 + ファイル名引数 (なし ./ プレフィックス)。

関連している:

うーん、パスでBasename&Dirnameがそれをカットしず、パスを歩くのが難しい場合(親がパスをエクスポートしなかったらどうでしょう!)。ただし、シェルはスクリプトに開いたハンドルを持たなければならず、バッシュではハンドルは#255です。

SELF=`readlink /proc/$$/fd/255`

私にとっては役に立ちます。

多くの答えを要約すると、次のようになります。

    Script: "/tmp/src dir/test.sh"
    Calling folder: "/tmp/src dir/other"

使用するコマンド

    echo Script-Dir : `dirname "$(realpath $0)"`
    echo Script-Dir : $( cd ${0%/*} && pwd -P )
    echo Script-Dir : $(dirname "$(readlink -f "$0")")
    echo
    echo Script-Name : `basename "$(realpath $0)"`
    echo Script-Name : `basename $0`
    echo
    echo Script-Dir-Relative : `dirname "$BASH_SOURCE"`
    echo Script-Dir-Relative : `dirname $0`
    echo
    echo Calling-Dir : `pwd`

出力:

     Script-Dir : /tmp/src dir
     Script-Dir : /tmp/src dir
     Script-Dir : /tmp/src dir

     Script-Name : test.sh
     Script-Name : test.sh

     Script-Dir-Relative : ..
     Script-Dir-Relative : ..

     Calling-Dir : /tmp/src dir/other

見るhttps://pastebin.com/J8KjxrPF

これは bash-3.2 で動作します。

path="$( dirname "$( which "$0" )" )"

その使用例を次に示します。

持っていると言ってください ~/ビン ディレクトリにあります $パス. 。スクリプトがあります このディレクトリ内にあります。それ ソースのスクリプト ~/bin/lib/B. 。含まれているスクリプトが元のスクリプトと相対的な場所 (サブディレクトリ) がわかっています。 ライブラリ)、ただし、ユーザーの現在のディレクトリからの相対的な場所ではありません。

これは次のように解決されます(内部では ):

source "$( dirname "$( which "$0" )" )/lib/B"

ユーザーがどこにいても、スクリプトをどのように呼び出しても、これは常に機能します。

これらはいずれも、OS X の Finder によって起動される bash スクリプトでは機能しませんでした。最終的には次のものを使用しました。

SCRIPT_LOC="`ps -p $$ | sed /PID/d | sed s:.*/Network/:/Network/: |
sed s:.*/Volumes/:/Volumes/:`"

見た目は良くありませんが、仕事はうまくいきます。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top