結局のところ、bashの「。」と「source」に違いはありますか?


38

「。」の違いを探していました。また、「ソース」組み込みコマンドといくつかのソース(たとえば、この説明やbashのマンページ)は、これらがまったく同じであることを示唆しています。

しかし、環境変数の問題に続いて、テストを実施しました。次testenv.shを含むファイルを作成しました。

#!/bin/bash
echo $MY_VAR

コマンドプロンプトで、次を実行しました。

> chmod +x testenv.sh
> MY_VAR=12345
> ./testenv.sh

> source testenv.sh
12345
> MY_VAR=12345 ./testenv.sh
12345

[最初のフォームが空の文字列を返したことに注意してください]

したがって、この小さな実験は、「ソース」コマンドの場合、子環境が「。」の場合、親環境からすべての変数を継承するという違いあることを示唆しています。そうではありません。

私は何かを見逃していますか、これは文書化されていない/廃止されたbashの機能ですか?

[GNU bash、バージョン4.1.5(1)-release(x86_64-pc-linux-gnu)]

回答:


68

短い答え

あなたの質問では、2番目のコマンドは.シェル組み込みコマンドも組み込みコマンドも使用していませんsource。代わりに、他の実行可能ファイルと同じように名前でスクリプトを呼び出すことにより、実際に別のシェルでスクリプトを実行しています。これは(かかわらず、それを変数の別のセットを与えないあなたがいる場合エクスポート変数を親シェルで、それはすべての子プロセスの環境変数となり、そのため、子シェルの変数に含まれます)。を/スペースに変更すると、.組み込みで実行されsourceます。これはと同等です。

拡張説明

これはsourceシェル組み込みの構文で、現在のシェル内のスクリプトの内容を実行します(したがって、現在のシェルの変数を使用します)。

source testenv.sh

これは.組み込みの構文であり、次と同じことを行いsourceます。

. testenv.sh

ただし、次の構文はスクリプトを実行可能ファイルとして実行し、新しいシェルを起動して実行します。

./testenv.sh

それは.組み込みを使用していません。むしろ、.実行中のファイルへのパスの一部です。一般的に、少なくとも1 /文字を含む名前で起動することにより、シェルで実行可能ファイルを実行できます。./したがって、現在のディレクトリでファイルを実行するには、その前にファイルを置くのが最も簡単な方法です。現在のディレクトリがにない限り、PATHコマンドでスクリプトを実行することはできませんtestenv.sh。これは、PATH環境変数にリストされているディレクトリに存在するシステムコマンドまたはその他のファイルを実行するときに、現在のディレクトリのファイルを誤って実行することを防ぐためです。

ファイルを(sourceまたはではなく.)名前で実行すると、新しいシェルで実行されるため、独自のシェル変数のセットがあります。新しいシェル呼び出しプロセス(この場合は対話型シェル)から環境変数を継承し、それらの環境変数は新しいシェルのシェル変数になります。ただし、シェル変数を新しいシェルに渡すには、次のいずれかが必要です。

  1. シェル変数がエクスポートされたため、環境変数になりました。exportこれには組み込みのシェルを使用します。例では、を使用export MY_VAR=12345して変数を1ステップで設定およびエクスポートできますexport MY_VAR。既に設定されている場合は、単に使用できます。

  2. シェル変数は、実行中のコマンドに対して明示的に設定および渡されるため、実行中のコマンドの実行中は環境変数になります。これは通常、次のことを実現します。

    MY_VAR=12345 ./testenv.sh

    場合はMY_VAR、エクスポートされていないシェル変数をある、あなたも実行することができますtestenv.shMY_VARて、環境変数として渡された自分自身にそれを設定します

    MY_VAR="$MY_VAR" ./testenv.sh

./ スクリプトの構文を機能させるにはハッシュバンラインが必要です(正確に)

ちなみに、上記の名前で実行可能ファイルを呼び出した場合(.またはsourceシェル組み込みコマンドではなく)、実行するシェルプログラムは通常、実行元のシェルによって決定されないことに注意してください。代わりに:

  • バイナリファイルの場合、カーネルはその特定の種類のファイルを実行するように構成できます。ファイルの最初の2バイトを調べて、それがどのようなバイナリ実行可能ファイルであるかを示す「マジックナンバー」を探します。これが、実行可能バイナリの実行方法です。

    もちろん、これは非常に重要です。なぜなら、スクリプトは、実行可能なバイナリであるシェルまたは他のインタープリターなしでは実行できないからです!さらに、多くのコマンドとアプリケーションは、スクリプトではなくコンパイルされたバイナリです。

    #!テキストの実行可能ファイルを示す「マジックナンバー」のテキスト表現です。)

  • シェルまたは他のインタプリタ言語で実行することになっているファイルの場合、最初の行は次のようになります。

    #!/bin/sh

    /bin/shプログラムを実行するための他のシェルまたはインタープリターで置き換えられます。たとえば、Pythonプログラムは次の行で始まる場合があります。

    #!/usr/bin/python

    これらの行は、hashbang、shebang、および他の多くの同様の名前と呼ばれます。このFOLDOCエントリ、このウィキペディアの記事、および#!/ bin / shはインタープリターによって読み取られますか?詳細については。

  • テキストファイルがされている場合は、実行可能とマークし、あなたは(のようなあなたのシェルから実行します./filename)が、それはしていませんで始まり#!、カーネルは、それを実行に失敗しました。ただし、これが発生すると、シェルはその名前を何らかのシェルに渡して実行しようとします。ありますいくつかの要件に置かそれは(あるシェル「シェルは、シェルが起動されたとコマンド相当を実行するものとは...」)。実際には*を含むいくつかのシェルbashは自分自身の別のインスタンスを実行し、他のは/bin/sh。これを避けて、代わりにhashbang行を使用することを強くお勧めします(または、スクリプトを目的のインタープリター(例:)に渡すことで実行しますbash filename)。

    * GNU Bashマニュアル3.7.2コマンドの検索と実行:「ファイルが実行可能な形式ではなく、ファイルがディレクトリではないためにこの実行が失敗した場合、シェルスクリプトであると見なされ、シェルは説明どおりに実行しますでシェルスクリプト。」


2
私が便利だsourceと思ったのは、関数をbashからロードまたは再起動する必要なく利用できるようになったことです。例#!/bin/bash function olakease {echo olakease;}。一度ロードsource file.shするとolakease、bashから直接呼び出すことができます。本当に好きです。ソースが実行され、多くのものがロードされます。ドット.は実行専用で、使用のようなものですbash file.sh
m3nda

2
@ erm3ndaに.もこの動作があります。. file.shそしてsource file.sh、で定義されfile.shた関数を保持するなど、まったく同じことを行います。(おそらく、あなたは考えていますが./file.sh、これは異なります。しかし、それは組み込みを使用していませ.。代わり.に、パスの一部です。)
エリアカガン

ああ、私は。[space]ファイルを注意深く読みませんでした。本当にありがとうございます。
m3nda

13

はい、あなたは何かを見逃しています。

「。」を混同していると思います。つまり、現在のディレクトリを意味./testenv.shし、「。」つまりsource、組み込みコマンドです。したがって、「。」の場合 というsourceこと. ./testenv.shです。理にかなっていますか?

だからこれを試してください:

MY_VAR=12345 
. ./testenv.sh

2
./それはそれを見つけることができませんでした場合、それは、それなしで、bashが最初のPATHに目を通すするファイルは、現在のディレクトリを試す場所を正確にそれを伝えます。bashがPOSIXモードで実行されている場合、ファイルへのパス(など./)を指定しないと、PATHのみが検索され、現在のディレクトリがPATHにない場合はファイルの検索に失敗します。
ガイラ

@geirhaはい、あなたは正しいです、sourceそして(そして.)彼らは通常の意味で実際にスクリプトを実行していなくても、実際に最初に$ PATHをチェックします。私(元)のコメントが間違っていました。
エリアケイガン

短く、ポイント+1
デビッドモラレス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.