web-dev-qa-db-ja.com

pwdと/ bin / pwdの奇妙な違い

ln -s . aaを使用して、現在のディレクトリにシンボリックリンクを追加しました。 cd aaを実行し、その後pwdを実行すると、応答は/home/sim/aaになります。

しかし、/bin/pwdを実行すると、/home/simが出力されます(現在のディレクトリは変更されていません)。

この違いはどこから来るのですか?

15
user3581976

Bashを含むほとんどのシェルでは、pwdはシェル組み込みです。

$ type -a pwd
pwd is a Shell builtin
pwd is /bin/pwd

/bin/pwdを使用する場合は、-Lオプションを使用して、組み込みpwdと同じ結果を取得する必要があります。

$ ln -s . test
$ cd test && pwd
/home/cuonglm/test
$ /bin/pwd
/home/cuonglm
$ /bin/pwd -L
/home/cuonglm/test

デフォルトでは、/bin/pwdはシンボリックリンクを無視し、実際のディレクトリを出力します。

info pwd から:

`-L'
`--logical'
     If the contents of the environment variable `PWD' provide an
     absolute name of the current directory with no `.' or `..'
     components, but possibly with symbolic links, then output those
     contents.  Otherwise, fall back to default `-P' handling.

`-P'
`--physical'
     Print a fully resolved name for the current directory.  That is,
     all components of the printed name will be actual directory
     names--none will be symbolic links.

組み込みのpwdにはデフォルトでシンボリックリンクが含まれていますが、-Pオプションが使用されているか、-o physical set組み込みが有効になっています。

man bash から:

pwd [-LP]
              Print the absolute pathname of the  current  working  directory.
              The pathname printed contains no symbolic links if the -P option
              is supplied or the -o physical option to the set builtin command
              is  enabled.  If the -L option is used, the pathname printed may
              contain symbolic links.  The return status is 0 unless an  error
              occurs  while  reading  the  name of the current directory or an
              invalid option is supplied.
17
cuonglm

プロセスがファイルシステムに問い合わせて、現在の作業ディレクトリを特定することは可能です。この質問に対する回答としてトピックにするには少し複雑すぎる方法を使用します。これは、pwdプログラムとgetcwdライブラリ関数が行うことです。 Unixの初期の頃は、作業ディレクトリが何であるかを見つける唯一の方法でした。これは、他の回答、またはこのサイトの他のどこにも私が見つけることができない、あなたの質問に対する回答の一部です(42秒相当の検索の後)。

  • シェルが起動すると、現在の作業ディレクトリを取得します(おそらくgetcwdを呼び出すことにより)。
  • その後、cdpushd、またはpopdを実行すると、シェルが追跡します文字列操作関数を使用して作業ディレクトリの。例えば、

    • 作業ディレクトリが/home/simで、cd ..と入力すると、シェルは作業ディレクトリが/homeであると計算します。
    • 作業ディレクトリが/home/simで、cd .と入力すると、シェルは作業ディレクトリが/home/simであると計算します。
    • 作業ディレクトリが/home/simで、cd aaと入力すると、シェルはaaがシンボリックリンクかどうかを確認せずに、作業ディレクトリが/home/sim/aaであると計算します。

    これは、getcwdを呼び出す「コスト」を節約するために行われます。しかし、これは不正確な情報をもたらす可能性があるため、トレードオフです。

  • pwd(組み込み)コマンドは、作業ディレクトリが何であるかをシェルが記憶/計算した概念を表示するだけです。
  • また、シェルは、ユーザープロセスのconvenienceのために、作業ディレクトリが何であるかという記憶/計算された概念をPWD環境変数に入れます。正確な情報が必要な場合、プロセスはこれに依存するべきではありません。

要するに、シェルはそれがどこにあるのか混乱する可能性があるということです。ただし、/bin/pwdと入力すると、シェルの作業ディレクトリの概念にアクセスできない別のプロセスで実行されるため、昔ながらの方法で実際の作業ディレクトリ自体が決定されます。 (例外:/bin/pwdプログラムcanはPWD環境変数を確認できますが、-Lを指定すると明らかに実行されます。)シェルが混乱する別の例を次に示します。

cd /home/sim/aa #/home/home/sim、および/home/sim/aa
#はすべて実際のディレクトリです(シンボリックリンクではありません)。
pwd #出力:/home/sim/aa、これは正しいです。
mv ../aa ../bb
pwd #出力:/home/sim/aa、これは正しくありません。
/bin/pwd #出力:/home/sim/bb、これは正しいです。


そして、これが明確でない場合に備えて、ln -s . aaおよびcd aaと入力すると、現在の作業ディレクトリは変更されませんcd .を入力したときのそれ以上–これは、cd aaを入力したときの本質的なことです。

7
Scott