bashで実行するために、実行可能ファイルまたはスクリプト名の前に./(ドットスラッシュ)が必要なのはなぜですか?


288

bashでスクリプトを実行するとき./は、最初に次のように記述する必要があります。

$ ./manage.py syncdb

そうしないと、エラーメッセージが表示されます。

$ manage.py syncdb
-bash: manage.py: command not found

これの理由は何ですか?私.は現在のフォルダのエイリアスだと思ったので、これらの2つの呼び出しは同等でなければなりません。

また./、次のようなアプリケーションを実行するときになぜ必要がないのかわかりません。

user:/home/user$ cd /usr/bin
user:/usr/bin$ git

(それなしで実行されます./


4
これは、私がこれまでに遭遇した問題に関する最高のドキュメントです。linfo.org
odigity

回答:


307

Unixでは、通常、現在のディレクトリはにありません$PATH

コマンドを入力すると、シェルはPATH変数で指定されたディレクトリのリストを検索します。現在のディレクトリはそのリストにありません。

そのリストに現在のディレクトリがない理由はセキュリティです。

あなたがrootで、別のユーザーのディレクトリに移動して、のsl代わりに入力したとしlsます。現在のディレクトリがにあるPATH場合、シェルはslそのディレクトリでプログラムを実行しようとします(他のslプログラムがないため)。そのslプログラムは悪意があるかもしれません。

それはで動作する./ので、POSIXが指定含まれているコマンド名があること/で、検索を抑制し、直接ファイル名として使用されます$PATH。まったく同じ効果を得るにはフルパスを使用することもできますが、./短くて書くのが簡単です。

編集

そのsl部分はほんの一例でした。内のディレクトリPATHが順番に検索され、一致するとそのプログラムが実行されます。したがって、PATH見た目によっては、通常のコマンドを入力するだけでは、現在のディレクトリでプログラムを実行するのに十分でない場合があります。


47
何も間違える必要はありません。ユーザーは、ls実行可能ファイルを含む悪意のあるパッケージをダウンロードした可能性があります。
ジュリアーノ

13
これはUnixではなくWindowsでのみであると言うすべての人へのメモです。これは.\my.bat
Powershell

1
@gaearon ergh、私は「エイリアスではない」と言いましたが、それは「厳密にエイリアスである」はずでした。
Charles Duffy

4
それは非常に役立つ説明でした。20年以上前にDOSで少し作業したとき、CMDは現在のディレクトリ(THEN the PATH)をチェックするので、Linuxの動作は期待したものではありませんでしたが、それは非常に理にかなっています。
TecBrat、2013

2
@cnicutar:おもしろいことに、今日はsl蒸気機関車と呼ばれるコマンドがあることがわかりましたが、デフォルトでは使用できません;-)
blackSmith

51

bashがコマンドラインを解釈するとき、環境変数に記述されている場所でコマンドを探します$PATH。それを表示するには、次のように入力します。

echo $PATH

コロンで区切られたパスがいくつかあります。ご覧のとおり、現在のパス.は通常にはありません$PATH。そのため、コマンドが現在のディレクトリにある場合、Bashはコマンドを見つけることができません。次のようにすることで変更できます。

PATH=$PATH:.

この行は現在のディレクトリを追加する$PATHので、次のことができます:

manage.py syncdb

セキュリティ上の問題があるため、お勧めしません。また.、ディレクトリによって異なりますが、奇妙な動作をする可能性があります。

避ける:

PATH=.:$PATH

いくつかの標準的なコマンドを「マスク」して、セキュリティ侵害の扉を開くことができるので:)

ちょうど私の2セント。


42

シェルが$PATHスクリプトを見つけるために環境変数を調べても、ホームディレクトリにあるスクリプトは見つかりません。

./「私のスクリプトの現在のディレクトリに見てではなく、中に指定されたすべてのディレクトリを見ていると言います$PATH」。


5

「。」を含める場合 基本的に、実行可能なbashスクリプトへの「完全パス」を指定しているため、シェルはPATH変数を確認する必要がありません。「。」なし シェルはPATH変数を調べます(実行echo $PATHすると、入力したコマンドがPATHのいずれかのフォルダーにあるかどうかを確認できます。そうでない場合(manage.pyの場合のように)、そうではありません。ファイルを見つけることができません。現在のディレクトリをPATHに含めることは悪い習慣と考えられています。これについては、ここで合理的に説明されています。 13.html


2

* nixでは、Windowsとは異なり、通常、現在のディレクトリは$PATH変数にありません。したがって、コマンドの実行時に現在のディレクトリは検索されません。./これらのアプリケーション $ PATHにあるため、アプリケーションを実行する必要はありません。ほとんどの場合、それらは/binまたはにあり/usr/binます。


1

この質問にはすでに素晴らしい回答がいくつかありますが、実行可能ファイルがPATH上にあり、実行時に非常に異なる出力が得られる場合は、それを追加したいと思います

./executable

あなたが実行した場合に得るものに

executable

(たとえば、どちらか一方ではエラーメッセージが表示されるとしましょう)、問題は、マシン上に実行可能ファイルの2つの異なるバージョンがあることです。1つはパス上にあり、もう1つはパス上にありません。

実行してこれを確認してください

どの実行可能ファイル

そして

whereis executable

それは私の問題を修正しました... 3つのバージョンの実行可能ファイルがあり、そのうちの1つだけが環境用に正しくコンパイルされました。


0

/POSIX PATHルールの根拠

このルールについては、bashで実行するために実行可能ファイルまたはスクリプト名の前に./(ドットスラッシュ)が必要なのはなぜですか。でもそれがいいデザインだと思う理由をもう少し詳しく説明したいと思います。

まず、ルールの明示的な完全バージョンは次のとおりです。

  • パスが含まれている場合/(例えば./someprog/bin/someprog./bin/someprog):CWDが使用され、PATHではありません
  • パスに含まれない場合/(例someprog:):PATHが使用され、CWDは使用されません

ここで、次のように実行するとします。

someprog

検索します:

  • 最初にCWDを基準
  • 後のPATHを基準

次に、/bin/someprogディストリビューションから実行したい場合は、次のようにします。

someprog

他の無関係なsomeprogプログラムが含まれているディレクトリにいる可能性があるため、動作することもありますが、失敗することもあります。

したがって、これは信頼できないことをすぐに理解し、PATHを使用したい場合は常に絶対パスを使用することになり、PATHの目的が無効になります。

これはまた、PATHに相対パスを含めることが非常に悪い考えである理由でもあります。私はあなたを見ていますnode_modules/bin

逆に、以下を実行するとします。

./someprog

検索します:

  • 最初にPATHを基準
  • 後のCWDを基準

次に、someproggitリポジトリからスクリプトをダウンロードしてCWDから実行したい場合は、これが実際に実行されるプログラムであるかどうか確信が持てません。

/bin/someprog

これは、昨年のクリスマスの後に飲み過ぎてインストールしたパッケージのPATHに含まれています。

したがって、繰り返しますが、実行しているものを知るために、フルパスを使用してCWDに相対的なローカルスクリプトを常に実行する必要があります。

"$(pwd)/someprog"

これも非常に迷惑です。

思いつきそうなもう1つのルールは次のとおりです。

相対パスはPATHのみを使用し、絶対パスはCWDのみを使用します

ただし、これにより、ユーザーはで非PATHスクリプトに常に絶対パスを使用する必要があります"$(pwd)/someprog"

/パスサーチルールを約問題の解決策を覚えて簡単なを提供しています:

  • スラッシュ:使用しない PATH
  • スラッシュなし:使用のみ PATH

これは、現在のディレクトリ内のファイルは、のいずれかで表現することができるという事実に依存することによって、それが超簡単常にあなたが実行されているものを知ることができる./somefilesomefile、そしてそれが彼らのいずれかに特別な意味を与えるようにします。

ときどき、とsome/prog比較して検索できないのが少し面倒ですがPATH、これに対するより正解はありません。


-1

スクリプトがパスにない場合は、そうする必要があります。詳細については、http: //www.tldp.org/LDP/Bash-Beginners-Guide/html/sect_02_01.htmlを参照してください


5
...参考までに、irc.freenode.orgの#bashでは、人々がTLDP(特にAdvanced Bash Guide)から学んだ誤解を常に修正しています。したがって、そこに人を向けることは...理想的ではないかもしれません。(私たちの好ましい紹介ドキュメントはmywiki.wooledge.org/BashGuideです
Charles Duffy

-2

すべての質問に素晴らしい答えがあります。そうです、これは、絶対パスを含めない限り、現在のディレクトリで実行する場合にのみ当てはまります。以下のサンプルをご覧ください。

また、子フォルダーtmp2(/ tmp / tmp2)でコマンドを実行し、(二重のドットスラッシュ)を使用している場合、(ドットスラッシュ)は意味をなします。

サンプル:

[fifiip-172-31-17-12 tmp]$ ./StackO.sh

Hello Stack Overflow

[fifi@ip-172-31-17-12 tmp]$ /tmp/StackO.sh

Hello Stack Overflow

[fifi@ip-172-31-17-12 tmp]$ mkdir tmp2

[fifi@ip-172-31-17-12 tmp]$ cd tmp2/

[fifi@ip-172-31-17-12 tmp2]$ ../StackO.sh

Hello Stack Overflow
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.