現在の作業ディレクトリをスクリプトのディレクトリに設定するにはどうすればよいですか?


569

私はbashスクリプトを書いています。現在の作業ディレクトリが常にスクリプトが置かれているディレクトリである必要があります。

デフォルトの動作では、スクリプトの現在の作業ディレクトリは、それを実行するシェルのディレクトリですが、この動作は必要ありません。


/ usr / binなどのラッパースクリプトを(ハードコードされた)適切なディレクトリにcdしてスクリプトを実行することを検討しましたか?
Dagg Nabbit、2010

2
なぜスクリプトのディレクトリが必要なのですか?おそらく根本的な問題を解決するためのより良い方法があるでしょう。
bstpierre 2010

12
あなたが「明らかに望ましくない」と呼ぶ動作は実際には完全に必要であることを指摘したいのですが、実行するmyscript path/to/fileと、スクリプトが発生するディレクトリではなく、現在のディレクトリに対する相対パス/ファイル/ファイルを評価するスクリプトが期待されます。また、ssh remotehost bash < ./myscriptBASH FAQで言及されているように、スクリプトを実行するとどうなるでしょうか。
Gordon Davisson、


3
cd "${BASH_SOURCE%/*}" || exit
2017

回答:


656
#!/bin/bash
cd "$(dirname "$0")"

7
dirnameは '。'を返します Windowsでbashを使用する場合。ですから、パウロの答えはより良いです。
Tvaroh 2013年

7
「。」も返します マックOSXで
ベン・クレイトン

4
シンボリックリンクがの一部を構成する場合、物事が壊れることがあることに注意する価値があります $0。たとえば、../../スクリプトでは、スクリプトの場所の2つ上のレベルのディレクトリを参照することが期待できますが、シンボリックリンクが機能している場合は、必ずしもそうとは限りません。
Brian Gordon、

20
スクリプトをとして呼び出した場合./script.は正しいディレクトリであり、それに変更する.と、scriptが配置されているディレクトリそのもの、つまり現在の作業ディレクトリに移動します。
ndim 2014

6
このように現在のディレクトリからスクリプトを実行するbash script.shと、の値$0はになりscript.shます。cdコマンドが「機能する」唯一の方法は、失敗したコマンドを気にしないためです。set -o errexit(別名:)を使用しset -eて、スクリプトが失敗したコマンドを破棄しないようにする場合cd script.sh、エラーのため、これは機能しません。信頼できる[bash固有の]方法はcd "$(dirname ${BASH_SOURCE[0]})"
次のとおり

322

以下も機能します:

cd "${0%/*}"

構文は、この StackOverflowの回答で完全に説明されています。


17
:それはどのように動作するかを説明stackoverflow.com/questions/6393551/...
kenorb

25
パスに空白が含まれている場合は、引用符で囲むことを忘れないでください。ie cd "$ {0%/ *}"
H.Rabiee 2013

17
スクリプトがで呼び出された場合、これは失敗したbash script.sh- $0ちょうどファイルの名前になります
クリス・ワット

17
この答えは簡潔すぎると思います。構文についてはほとんど何も学びません。これを読む方法についてのいくつかの説明は役に立ちます。
2016

2
このトリックはサブシェルも生成しないため、スピードフリークに適しています。
teknopaul 2017

184

次の簡単なワンライナーを試してください:


すべてのUNIX / OSX / Linuxの場合

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

バッシュ

dir=$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)

注:コマンドでは、2つのダッシュ(-)を使用してコマンドオプションの終わりを示します。そのため、ダッシュやその他の特殊文字を含むファイルはコマンドを中断しません。

注:Bashではを使用${BASH_SOURCE[0]}してください。$0そうしないと、ソース(source/ .)を取得するときにパスが壊れる可能性があります。


Linux、Macおよびその他の* BSDの場合:

cd "$(dirname "$(realpath "$0")")";

注:realpathデフォルトで最も人気のあるLinuxディストリビューション(Ubuntuなど)にインストールする必要がありますが、インストールされていない場合があるため、インストールする必要があります。

注:Bashを使用${BASH_SOURCE[0]}している場合はを使用してください。$0そうしないと、ソース(source/ .)を取得するときにパスが壊れる可能性があります。

そうでなければ、あなたはそのようなものを試すことができます(最初の既存のツールを使用します):

cd "$(dirname "$(readlink -f "$0" || realpath "$0")")"

Linux固有の場合:

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

* BSD / MacでGNU readlinkを使用:

cd "$(dirname "$(greadlink -f "$0")")"

注:coreutilsインストールが完了している必要があります(例1. Homebrewをインストールする、2。brew install coreutils)。


バッシュで

bash では、次のように、パラメータ拡張を使用してそれを実現できます。

cd "${0%/*}"

ただし、スクリプトが同じディレクトリから実行されている場合は機能しません。

または、bashで次の関数を定義できます。

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

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

または、Debian .bashrcファイルから取得したバージョンは次のとおりです。

function realpath()
{
    f=$@
    if [ -d "$f" ]; then
        base=""
        dir="$f"
    else
        base="/$(basename "$f")"
        dir=$(dirname "$f")
    fi
    dir=$(cd "$dir" && /bin/pwd)
    echo "$dir$base"
}

関連:

以下も参照してください。

MacでGNUのreadlink -fの動作を取得するにはどうすればよいですか?


4
syslinksを解決し、さまざまなOSを考慮に入れるため、一般的なものよりもはるかに良い答えです。ありがとう!
デニス

この回答をありがとう。一番上のものは私のMacで動作しました...しかしcp、@ kenorbコマンドで-スイッチは何をしますか?
TobyG 2014年

3
--コマンドでは二重ダッシュ()を使用してコマンドオプションの終わりを示します。そのため、ダッシュやその他の特殊文字を含むファイルはコマンドを中断しません。例えば試し経由でファイルを作成touch "-test"し、touch -- -testその後、経由してファイルを削除し、rm "-test"かつrm -- -test、その差を参照してください。
ケノーブ2014年

1
実パスが廃止されました:私はできれば私は私のupvoteを削除したいunix.stackexchange.com/questions/136494/...
LSH

1
@lsh realpath廃止予定のパッケージはGNUではなく、Debianのみであることを示していますrealpath。はっきりしないと思われる場合は、編集を提案できます。
kenorb 2015年

73
cd "$(dirname "${BASH_SOURCE[0]}")"

それは簡単です。できます。


1
これは受け入れられる答えになるはずです。OSXおよびLinux Ubuntuで動作します。
David Rissato Cruz

5
これは、スクリプトBが他のスクリプトAから供給されており、スクリプトBからの相対パスを使用する必要がある場合に適切に機能します。ありがとうございます。
Enrico

5
これは、Windowsに触れなければならないほど残念な私たちのためにCygwinでも機能します
Bruno Bronosky、2016

3
またはcd "${BASH_SOURCE%/*}" || exit
2017

macOS Mojaveで動作します
Juan Boero

6

受け入れられた回答は、などのほかの場所でシンボリックリンクされていないスクリプトに適しています$PATH

#!/bin/bash
cd "$(dirname "$0")"

ただし、スクリプトがシンボリックリンクを介して実行される場合、

ln -sv ~/project/script.sh ~/bin/; 
~/bin/script.sh

この意志のCD ~/bin/ディレクトリではなく~/project/、おそらくあなたのスクリプトを中断しますディレクトリは、の目的は、以下の場合cdに比べて依存関係を含めることです~/project/

シンボリックリンクの安全な答えは以下のとおりです。

#!/bin/bash
cd "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")"

readlink -f シンボリックリンクされる可能性のあるファイルの絶対パスを解決するために必要です。

引用符は、空白を含む可能性のあるファイルパスをサポートするために必要です(悪い習慣ですが、これが当てはまらないと想定するのは安全ではありません)。


4

このスクリプトは私にとってはうまくいくようです:

#!/bin/bash
mypath=`realpath $0`
cd `dirname $mypath`
pwd

pwdコマンドラインは、どこから実行しても、スクリプトの場所を現在の作業ディレクトリとして表示します。


3
realpathどこにでもインストールされる可能性は低いです。OPの状況によっては、問題にならない場合もあります。
bstpierre 2010

私のシステムにはありませんがrealpathreadlink似ているように見えます。
追って通知があるまで一時停止。

2
デフォルトでリアルパスがインストールされていないディストリビューションはどれですか?Ubuntuにはそれがあります。
ケノーブ2013


1
cd "`dirname $(readlink -f ${0})`"

あなたの答えを説明していただけますか?
Zulu

1
このコードは問題の解決に役立つ可能性がありますが、なぜまたはどのように質問に答えるは説明していません。この追加のコンテキストを提供すると、その長期的な教育的価値が大幅に向上します。回答を編集して、適用される制限や前提条件などの説明を追加してください。
Toby Speight 2016年


-6

現在の作業ディレクトリを印刷する必要があるだけなら、これに従うことができます。

$ vim test

#!/bin/bash
pwd
:wq to save the test file.

実行権限を付与します。

chmod u+x test

次に、スクリプトを実行すると、./test現在の作業ディレクトリが表示されます。


2
問題は、スクリプトが独自のディレクトリで実行されるようにする方法でした(作業ディレクトリでない場合を含む)。したがって、これは答えではありません。とにかく、なぜこれを実行するだけでなく...実行するのpwdですか?無駄なキー入力がたくさんあるようです。
underscore_d
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.