なぜcdはプログラムではないのですか?


129

なぜcdプログラムではないのかといつも疑問に思っていましたが、答えを見つけることができませんでした。

なぜそうなのか誰でも知っていますか?



1
元のunix cdコマンドは別のプログラムであったことを読んだことを覚えています(どこにあるかわかりません)。シェルはそれがなかった特別であること、それを処理しfork、ちょうどexec。そして、cd完了するとexecになりshます。これが本当の話かどうかはわかりません。
-camh

ポイントは何でしょうか?特別な処理を追加する場合は、chdirsyscallを呼び出すこともできます。ソース:v1 v5 v7(Bourneシェルを使用した最初のバージョン)
Mikel

2
@camh、それは実話です。私はデニスM. Ritchie氏によって書かれた記事、「UNIXタイムシェアリングシステムの進化」、AT&Tベル研究所テクニカルジャーナル63(6)、パート2、10月1984年にすぎということを読んだ
jlliagre

@Mikel:私はそれが無意味に見えることに同意しますがcd、私は読んだことについての話を伝えていました。@jlliagreが詳細を記入したので、私は明らかにその側面について間違っていました。
-camh

回答:


172

cdコマンドは右、「現在の作業ディレクトリを」修正しますか?

「現在の作業ディレクトリ」は、各プロセスに固有のプロパティです。

したがって、cdプログラムであれば、次のように機能します。

  1. cd foo
  2. cdプロセスが開始されます
  3. cdこのプロセスは、ディレクトリ変更し、CDのプロセスのために
  4. cdプロセスが終了します
  5. シェルは、現在の作業ディレクトリを含め、開始前と同じ状態のままです。

8
5つのステップは正しいですが、「cdプログラムがこのように動作する場合」は「cd外部プログラムの実装で使用される場合、このように動作する」はずです。
jlliagre

1
システムプログラマーではなく、シェルとの相互作用についての深い知識も持っていないので、シェルが現在の作業ディレクトリを公開し、cdがそのプロパティにアクセスして変更するプログラムになることを期待していました。この答えを見た後、それはおそらく多くの理由で実際にどのように機能するかについて次善であると理解しています。
ジェイソン14年

108

cdシェル組み込みであることに加えて、実際 POSIX準拠OS上のプログラムもあります。のような通常のユーティリティ用に独立した実行可能ファイルを提供する必要がありますcd。これは、たとえば、SolarisAIX、HP-UX、およびOS Xの場合です。

明らかに、cd外部実装は現在のシェルディレクトリを変更しないため、ビルトインは依然として必須です。ただし、後者は依然として有用です。POSIXがこのcdコマンドの使用方法をどのように想定しているかを示す例を次に示します。

find . -type d -exec cd {} \;

POSIXシステムでは、このonelinerは、許可さcdれていないすべてのディレクトリについてエラーメッセージを報告します。ほとんどのGnu / Linuxディストリビューションでは、次のエラーメッセージで失敗します。

find: `cd': No such file or directory

また、元のUnixの共著者の1人による「cdがプログラムではないのはなぜですかという質問に対する答えがあります。非常に初期のUnix実装では、cdchdir当時綴られていた)外部プログラムでした。fork最初に実装された後、予期せず動作しなくなりました。

デニス・リッチーの引用:

歓喜の最中に、chdir(現在のディレクトリを変更)コマンドが機能しなくなったことが発見されました。コードの読み取りが多くあり、フォークの追加によってchdir呼び出しがどのように破損する可能性があるかについての内省が心配でした。最後に真実が明らかになりました。古いシステムでは、chdirは普通のコマンドでした。端末に接続された(一意の)プロセスの現在のディレクトリを調整しました。新しいシステムでは、chdirコマンドは実行するために作成されたプロセスの現在のディレクトリを正しく変更しましたが、このプロセスは即座に終了し、親シェルにはまったく影響しませんでした!chdirをシェル内で内部的に実行される特別なコマンドにする必要がありました。いくつかのコマンドのような関数には、ログインなどの同じプロパティがあります。

出典: Dennis M. Ritchie、「Unixタイムシェアリングシステムの進化」、AT&T Bell Laboratories Technical Journal 63(6)、Part 2、1984年10月、pp.1577–93

Unixバージョン1(1971年3月)chdirのマニュアルページの状態:

各コマンドを実行するための新しいプロセスが作成されるため、通常のコマンドとして作成された場合、chdirは無効になります。したがって、シェルによって認識および実行されます。


10
...したがって、明らかに、POSIXは独立したcd実行可能ファイルが存在することを義務付けていますが、何もしません(間違った引数で呼び出された場合にエラーメッセージを出力する可能性を除く)。奇妙な。
イルマリカロネン

4
まあ、それが本当なら、それはPOSIXで最も愚かなことではないでしょう。
カズ

5
POSIX CDページではまた、「cd現在のシェル実行環境に影響を与えるので、それは常にシェル通常のビルトインとして提供されています。」と言います。
ミケル

6
@Kaz、彼らはまったく別のものではありません。それらは同じことをしますが、組み込みのものだけが現在のシェルに影響します。
jlliagre

13
@カズ:私は事実を報告している間、私を愚かに電話しないでください。POSIXに賛成または反対するかもしれませんが、メッセンジャーを撃ってはいけません。
jlliagre

47

Bashの紹介から(シェルとは?):

シェルは、個別のユーティリティを介して取得することが不可能または不便な機能を実装する組み込みコマンド(組み込み)の小さなセットも提供します。例えば、cdbreakcontinue、および execそれらが直接シェル自体を操作するため)シェルの外部に実装することができません。historygetoptskill、またはpwd組み込みコマンドは、とりわけ、別のユーティリティで実施することができるが、それらはとして組み込みコマンドを使用する方が便利です。すべてのシェル組み込みコマンドについては、以降のセクションで説明します。


29

今年のエイプリルフールのために、私はのスタンドアロン版cdを書きまし

誰も冗談を言いませんでした。はぁ。

cdシェルに組み込む必要があるかどうかわからない場合は、ダウンロードしてビルドし、試してください。

そのマニュアルページも読んでください。:)


本当に便利なコード!:-)
dschulz

6
Gnu / LinuxをよりPOSIX準拠にするために働いている人に会えてうれしい。あなたの実装は良い冗談であるだけでなく、実際にはLinuxディストリビューションに欠けているものです...
jlliagre

8
来年、POSIXの問題を引用して、もう一度試すつもりだと思います。;)
ウォーレンヤング

6年後:そうですね
ピーターA.シュナイダー

@ PeterA.Schneider:私が冗談を言っていることは明らかだと思ったので、明確にするために、いや、実際にこれをOSやCygwinなどのOSに似たプロジェクトに取り込もうとする多くの努力を費やすつもりはありません欠乏/bin/cd。あなたが私のコードを取得して、それをあなた自身の個人的な探求にしたいなら、あなたはそうすることを歓迎します。
ウォーレンヤング

4

cdUnixでは、別のプロセス(親プロセスでさえも)の現在の作業ディレクトリを変更するメカニズムがないため、シェルのコマンドを個別のプロセスにすることはできません。

cd別のプロセスである場合、Unixでは不可能な親(シェル)の現在の作業ディレクトリを変更する必要があります。代わりcdに、特別な組み込みコマンドです。シェルは次のような機能を呼び出すchdir()fchdir() 、自身の現在の作業ディレクトリを変更します。

注:カーネルは、すべてのプロセスの現在の作業ディレクトリのiノード番号を保存します。子プロセスcwdは、親から継承します。


0

cdはシェル組み込みコマンドです。簡単です。男のCDはそれをすべて言います。cdコマンドは、すべてのインタープリターおよび(スレッド環境で)すべてのスレッドの作業ディレクトリーを変更します。


シェルは、現在の作業ディレクトリ($ PDW ...)またはcdable_varsを処理する環境であるためです。このビルトインは、最終的に、すべてのユーザーに表示されるコマンドが現在の作業ディレクトリを変更する方法です。そのようにテストすることができます:cd.cなしでbashをコンパイルし、すべての環境cdable_varsを処理しようとする独自のcdスクリプトを作成しようとします。この質問も開発者に関連しています。彼らはこの質問にもっと詳細に答えることができると思います。

2
あり非常に良い技術的な理由cd内蔵されているが。最高ランクの回答を読んで、回答を改善する方法を検討することをお勧めします。
トールビョーンラウンアンデルセン

最高ランクの答えは、私が今まで読んだ最悪の答えでした!でもね 私は誰!

3
しかし、それはなぜ疑問に答えます。
ソルビョーンラウンアンデルセン

-1

人々の答えに欠けていることの1つは、現在のディレクトリは各プログラムが変更できる環境変数であるということです。「export」コマンドを使用して現在の環境変数リストを表示すると、次のようになります。

declare -x PWD="/home/erfan"

結果に。したがって、「cd」コマンドによって、この内部変数を変更したいだけです。もちろん、試してみると、シェルのptyのPWD変数を変更できると思います。好む:

cder    #change current PTY $PWD variable

しかし、通常の場合は必要ないと思います。言い換えれば、bash(または任意のシェル)の助けを借りて、定義されている内部変数を変更します。


3
Bourneシェルが現在の作業ディレクトリ(CWD)を$ PWDとして公開しているのは事実ですが、それはプライマリストレージの場所ではありません。実際の場所は、カーネルのプロセスごとの構造です。したがって、CWDが「環境変数である」と言うのは誤りです。それはあなたがお勧めの方法を働いた場合は、このC 2-ライナーは印刷し..、パスを、パスではなく、あなたからそれを開始しました:#include <stdlib.h> int main(void) { chdir(".."); puts(getenv("PWD")); }(Cシェルは道で、代わりに%のCWDとしてCWDを公開します。)
ウォーレン・ヤング

アプリに別の行を追加してみましょう。#include <stdlib.h> int main(void){chdir( ".."); puts(getenv( "PWD")); setenv(P "PWD"、 "/"、1); puts(getenv( "PWD")); }結果として何が得られますか?
エルファンカム

3
これは変数の値を上書きするだけで、CWDに副作用はありません。これは、次の#include <unistd.h> int main(void) { char ac[99]; setenv("PWD", "/", 1); puts(getcwd(ac, sizeof(ac))); }ことを示すより良いテストです。:ではなく、プログラムを開始したディレクトリを表示します/
ウォーレンヤング

すべてのプロセスには作業ディレクトリとパス変数もあると思います。したがって、chdirによってプロセスのこの属性を変更するだけです。シェルにもこの属性があり、cdによってこの属性を変更します。
エルファンカム

4
いいえ、$PWDBourneシェルに対してのみ意味があることを伝えています。これは、シェルが知っていることをシェルスクリプトに伝えるための手段であり、シェルスクリプトはそれpwdを見つけるために呼び出す必要はありません。の値に依存するスタンドアロンプ​​ログラム$PWDは信頼できません。
ウォーレンヤング
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.