私はディレクトリへの絶対パス(Blink)でシンボリックリンクを作成し、たとえば次のツリーを持っています:
$ ls -l /tmp/A
total 0
lrwxrwxrwx 1 root root 6 Apr 3 12:27 Blink -> /tmp/B
-rw-r--r-- 1 root root 0 Apr 3 12:27 foo
$ ls -l /tmp/B
total 0
-rw-r--r-- 1 root root 0 Apr 3 12:27 bar
次に、/ tmp/Aに移動し、ディレクトリをBlinkに変更します。
$ cd /tmp/A
$ pwd
/tmp/A
$ cd Blink
$ pwd
/tmp/A/Blink
cd ..
は/tmp/A
に戻りますが、たとえばls ../foo
と入力すると、エラーが発生します。
ls: ../foo: No such file or directory
組み込みのcdコマンドは必要に応じてパスを解決しますが、外部のlsは..を/ tmp/Bの上位レベルと見なすため、fooを見つけることができません。
ここの問題は何ですか?/tmp/A/Blinkから../fooのような相対パスでfooファイルを取得できますか?
あなたはこれを行うことができないと思います。シェルは現在、ファイルシステムとOSに依存するだけでなく、現在の作業ディレクトリを名前で追跡するのではなく、現在の作業ディレクトリを追跡しています。つまり、組み込みのcd
は、「..」チェーンを直接たどるのではなく、シンボリックリンクを「バックアップ」できるということです。
ただし、_ls ../foo
_を実行すると、ls
は、シェルがシンボリックリンクをたどってディレクトリに到達したことを認識しません。 ls
は "../foo"に対してstat()
を実行します。 「..」の部分は現在のディレクトリからのもので、現在のディレクトリには親の「..」エントリが1つだけあります。全体のシンボリックリンクは、ディレクトリに単一の「。」がある方法を変更しません。および単一の「..」エントリ。シンボリックリンクを使用すると、カーネルは間接的な層をファイルパスに追加できます。 「../whatever」をopen()
またはstat()
に渡すと、カーネルは、呼び出しを実行しているプロセスの現在の作業ディレクトリを使用して、「 ……」.
シェルは現在の作業ディレクトリを$PWD
に保存します。これは、シェルの組み込み関数cd
とpwd
に使用されているもので、ご覧のとおり、シンボリックリンクを通常のディレクトリとして扱います。これが役立つ場合もあれば、役に立たない場合もあります。
pwd
を使用して実際のディレクトリを見つけることができます(詳細はhelp pwd
と入力してください):
$ pwd
/tmp/A/Blink
$ pwd -L
/tmp/A/Blink
$ pwd -P
/tmp/B
同様に、cd
にはオプション-P
があります(ここでもhelp cd
はあなたの友達です):
$ cd /tmp/A/Blink
$ pwd
/tmp/A/Blink
$ cd -P ..
$ pwd -P
/tmp
最後に、「機能」を完全にオフにすることができます。
$ set -P
$ cd /tmp/A/Blink
$ pwd
/tmp/B
ブルースとアムスは背後にある行動を説明する美しい答えを出しました。しかし実際にls ../foo
あなたが求めていた、あなたは次のようなもので行くことができます
ls $(dirname $PWD)/foo
/tmp/A/Blink
isは実際には/tmp/B
であるため、それを行うことはできません。したがって、ls ../A/foo
は機能します。
cdをrealに変換できると便利な場合がありますエイリアスされた/tmp/B
ではなく、/tmp/A/Blink
ディレクトリ。これを行うには、cd
の代わりに次の関数を使用できます(.bashrcに入れることができます)
lcd() { cd $(readlink -f "$1"); }
lcd
はもちろん、通常のディレクトリとシンボリックリンクされたディレクトリの両方で機能します。
注:readlink -f
は、リンクの最終ターゲットに作用します(リンクがデイジーチェーン接続されている場合)。