web-dev-qa-db-ja.com

現在のディレクトリを変更せずにサブディレクトリ内のシンボリックエイリアスファイル

サブディレクトリを移動せずに、1つのファイルをサブディレクトリ内の新しいファイルにシンボリックリンクするのは簡単なようです。しかし、構文についての何かは当惑し、私が期待するものに反しています。ここにテストケースがあります:

mkdir temp
cd temp
mkdir deploy
echo "Contents of the build file!" > deploy/resources.build.php
ln -s deploy/resources.build.php deploy/resources.php
cat deploy/resources.php #bad symlink

これは壊れたシンボリックリンクを作成するだけです!ビルド環境のセットアップスクリプトでこれを実行しているので、可能な場合は、現在の作業ディレクトリを変更しないようにします。

ln -s deploy/resources.build.php resources.php
cat deploy/resources.php

また、デプロイサブディレクトリではなく一時ディレクトリにシンボリックリンクを作成するため、機能しません。

cd deploy
ln -s resources.build.php resources.php
cd ..

これは機能しますが、ディレクトリを変更せずに実行する方法を知りたいと思います。

次のような完全パスを使用します。

/home/whatever/src/project/temp/stuff/temp/deploy/resources.build.php

機能しますが、特にプロジェクト環境がビルド間で異なる可能性があるビルド環境などでは、不可解でやや実用的ではありません。

サブディレクトリに移動したりサブディレクトリから移動したりせずに、サブディレクトリ内の2つのファイル間にシンボリックリンクを作成し、新しいファイルに「エイリアス」に新しい名前を付けるにはどうすればよいですか。

11
Kzqai

しかし、構文についての何かは当惑し、私が期待するものに反するものです。

lnの引数は、使用している形式では次のとおりです。

ln [OPTION] ... [-T] TARGET LINK_NAME(1番目のフォーム)

複雑で直感的でないことは、シンボリックリンクを作成しているとき、lnの-​​target引数はファイルへのパスではなく、作成するシンボリックリンク。少し考えてみれば、そのようにする必要があることは明らかです。検討してください:

$ echo foo >foo
$ ln -s foo bar1
$ ln -s $PWD/foo bar2
$ cat bar1
foo
$ cat bar2
foo
$ ls -l bar1 bar2
lrwxrwxrwx 1 matt matt  3 Dec 29 16:29 bar1 -> foo
lrwxrwxrwx 1 matt matt 29 Dec 29 16:29 bar2 -> /home/matt/testdir/foo

その例では、同じファイルを指す「bar1」と「bar2」という名前の2つのシンボリックリンクを作成します。 lsは、シンボリックリンク自体の内容が異なることを示しています。1つは絶対パスを含み、もう1つは相対パスを含みます。このため、1つが別のディレクトリに移動されても機能し続け、もう1つは機能しません。

$ mv bar2 /tmp
$ cat /tmp/bar2
foo
$ mv bar1 /tmp
$ cat /tmp/bar1
cat: /tmp/bar1: No such file or directory

したがって、相対シンボリックリンクと絶対シンボリックリンクの両方を作成できなければならず、後でターゲットファイルが作成されると壊れないシンボリックリンクを作成することさえできることを考えると、target引数を解釈する必要があります既存のファイルへのパスではなく、自由形式のテキストとして。

Deploy/resources.build.phpにリンクするdeploy/resources.phpという名前のファイルを作成する場合は、絶対シンボリックリンクを作成するかどうかを決定する必要があります(これは、移動されるシンボリックリンクに対して復元力がありますが、ターゲットが移動された)、または相対シンボリックリンク(シンボリックリンクとターゲットの両方が一緒に移動され、同じ相対パスを維持している限り、機能し続けます)。

絶対シンボリックリンクを作成するには、次のようにします。

$ ln -s $PWD/deploy/resources.build.php deploy/resources.php

相対パスを作成するには、まずソースからターゲットへの相対パスを把握します。この場合、ソースとターゲットは互いに同じディレクトリにあるので、次のようにすることができます。

$ ln -s resources.build.php deploy/resources.php

同じディレクトリにない場合は、代わりに次のようにする必要があります。

$ ln -s ../foo/f bar/b

その場合、たとえfoobarが両方とも現在のディレクトリにあるとしても、../lnに含める必要がありますtargetfを含むディレクトリからbを見つける方法について説明しているためです。

これは非常に長い説明ですが、うまくいけば、ln構文を少しよく理解するのに役立ちます。

10
godlygeek

次のように、サブシェルでリンクを作成できます。

  (cd deploy && ln -s resources.build.php resources.php && cat resources.php)

サブシェルが実行を終了しても、まだ正しいディレクトリにいることがわかります。

別の方法として、

 ln -s resources.build.php deploy/resources.php

これも機能し、CLにファイルresources.build.phpがコマンドを発行しているディレクトリにはないが、実際には./展開

3
MariusMatutiae

これは私がシンボリックリンクが基本的に設定ファイルであることを理解するまで私を混乱させました。つまり、そのパスデータを単純なテキストファイルにどのように書き込むのですか。

ln -s [target] [link name]

になる:

echo [target] > [link name]

私(そしておそらくOP)が犯していたエラーは、lnが対象としているファイルについて知る必要があると考えていることです。 lnは関係ありません。パス情報をファイルに書き込むだけです。これは完全に妥当なlnコマンドです:

ln -s /path/doesnt/exist/file.err
ll
file.err -> /path/doesnt/exist/file.err

したがって:

ln -s deploy/resources.build.php deploy/resources.php

resources.phpフォルダー内の./deployというsimlinkファイルが、フォルダーresources.build.php内のファイル./deploy/deploy/を参照して生成されます。

それはあなたが望むものではありそうになく、悪い(壊れた)リンクを与えます。リンクに問題はありません。そのファイルをそこに配置すると、リンクは機能します。しかし、(他の人が指摘したように)私とOPが望んだのは:

ln -s resources.build.php deploy/resources.php
1
Martin