/tmp
parent
Calledとに2つのフォルダを作成するとしますchild
。child
というファイルが含まれており、test-child.txt
というparent
ファイルが含まれていますtest-parent.txt
。さて、私はあなたparent
のためのシンボリックリンクを作成しましょうchild
。次に入ってからコピーしてみてchild
ください。 Bashの完了はうまく機能しますが、実際のファイルのコピーは失敗します。test-parent.txt
parent
cd /tmp
pwd
/tmp
mkdir parent
mkdir child
touch child/test-child.txt
ls child/
test-child.txt
cd parent
ln -sf ../child .
touch test-parent.txt
cd child
cp ../test-parent.txt .
cp: cannot stat ‘../test-parent.txt’: No such file or directory
なぜ? ?
そして私がそこにいる間、child
私がこう言ったら--
pwd
/tmp/parent/child
答え1
シェルはユーザーの便宜のためにシンボリックリンクに従います。これは、ディレクトリへのシンボリックリンクであってcd foo && cd ..
も、常に元のディレクトリに戻るのに良い効果があります。foo
これには2つの欠点があります。主な欠点は、他のプログラムではこの機能を実行しないことです。また、シンボリックディレクトリの追跡には独自の問題が発生します(シンボルリンクが変更された場合はどうなりますか?プロセスにシンボリックリンクを読み取る権限がない場合はどうなりますか?など)。
シェルはすべてのディレクトリの変更を追跡し、そこにどのように到達したかを覚えているため、これだけを実行できます。新しいプロセスが開始されると、この履歴情報は取得されません。後ろには、ルートディレクトリに到達するまでリンクに沿って現在のディレクトリを上に移動して..
場所を見つけます。
シンボリックリンクを介してディレクトリに到達した場合は、次のコマンドを使用してシンボリックリンクのパスを印刷できます。pwd
組み込みのシェルpwd -P
から別のプログラムを呼び出す場合は、..
シンボリックリンクコンポーネントを含むパスを渡さないでください。プログラムがこれを異なって解釈するからです。代わりに、以下を呼び出して..
コンポーネントを削除してくださいpwd -P
。
cp "$(cd .. && pwd -P && echo /)test-parent.txt" .
cd
シェルセッションで前のコマンドで使用されたシンボリックリンクを忘れるには、次のようにします。
cd "$(pwd -P && echo /.)"
これは現在のディレクトリに変更されるため、シェルプロセスの現在のディレクトリは効果的に変更されませんが、シェルが追跡する現在のディレクトリのパスを変更して、シンボリックリンクされていないリンクにします。
1これは伝統的に通話が機能する方法ですgetcwd
。一部のカーネルは現在のディレクトリを追跡しますが、以前のバージョンとの互換性の理由ではない場合(シンボリックリンクの微妙な場合もあるため)、シンボリックリンクは追跡しません。
答え2
cp
これは、シェルが同じリンクゲームを実行していないためです。あなたのシェルは現在の作業ディレクトリの間接参照として現在の作業ディレクトリへのリンクをたどっていますが、シェルが呼び出されたときにカーネルは話すべきではありません。代わりに、カーネルは現在の作業ディレクトリへの完全な絶対パスをcp
生成します。cp
作業ディレクトリ - したがって、リンクは.
シェルのリンクとは.
異なります.
。
現在の作業ディレクトリの絶対パスを簡単に確認でき、cd -P .
他のディレクトリにも同様に適用されますcd -P -- /any/other/directory
。少なくとものような印刷のための絶対パスでpwd
あり、多くのシェルでは絶対パスに変更されることもあります。.
pwd -P
$PWD
(同じ方法でcd -P .
)。
たとえば、
cd /tmp
mkdir -p parent child
cd parent
ln -s ../child child
touch ./child/somefile
cd -L child ###the default
printf %s\\n "$PWD"/*
cd -P .
printf %s\\n "$PWD"/*
出力
/tmp/parent/child/somefile
/tmp/child/somefile