web-dev-qa-db-ja.com

「ln」と「ln-s」の動作に一貫性がないように見える

ご存知のとおり、lnコマンドはリンクを作成します。デフォルトはハードリンクで、-sオプションはシンボリックリンクを作成します。一般的な構文はln [-s] OLD NEWです。ここで、OLDはリンク先のファイル、NEWは作成中の新しいファイルです。相互に内部のフォルダ間にハードリンクが作成される可能性があるため、ディレクトリにハードリンクを作成することはできません。コンピュータには、深刻な速度低下なしにこれをチェックするためのリソースがまだないようです。

リンクを作成するときは、両方のファイルのパスを書き出す必要があり、絶対パスでも相対パスでもかまいません。相対ファイルパスと絶対ファイルパスを混在させることができます。つまり、新しいファイル/フォルダの相対パスと古いファイル/フォルダの絶対パスを設定できます。相対パスを使用してハードリンクを作成する場合、両方のファイルのパスは現在のフォルダーを基準にしていますが、シンボリックリンクの場合、リンク先のファイル/フォルダーのパスは親フォルダーを基準にしていますが、古いファイルのパスです。/folderは、現在のフォルダーを基準にしています。なぜこれが私の質問に「相対的」なのか。

たとえば、HOMEフォルダー/home/user(別名~)にいて、フォルダーnewにファイルfileを使用して、newnew2の2つのフォルダーを作成するとします。 ln -s new/file new2/fileを試してみると、~/new2/fileから現在存在しない~/new2/new/fileへのリンクが壊れています。ただし、代わりにln -s ../new/file new2/fileを実行すると、期待される結果が得られます。これは、~/new2/fileから~/new/fileへのリンクです。

だから、私の質問:

シンボリックリンクのOLDファイル/フォルダーのファイルパスがその親を基準にしているのに、他の3つのパス(ハードリンクOLD、NEWファイル、シンボリックリンクNEWファイル/フォルダー)が現在のフォルダーを基準にしているのはなぜですか?

これはすべてFedoraにありますが、ほとんどのUNIXベースのOSに当てはまると確信しています。

[〜#〜] edit [〜#〜] E Carter Youngは、私の2番目の質問(および私の最初の質問、とにかく間違っていた)に関して頭に釘を打ったようです。シンボリックリンクの場合、ターゲットはまだ存在している必要はないようです。そのため、システムは現在のディレクトリではなく、リンクを基準にしてパスを作成する必要があります。しかし、コマンドの実行時に、ユーザーにパスが何であるかを理解させて自分で入力させるのではなく、シェルがそのパスを解析できないのはなぜですか?シェルはかなりうまく解析されているようですが、これはレガシー問題の場合ですか?パフォーマンスの問題?何?

1
trysis

マニュアルページを読んでください:質問1 =第1フォーム、これはLinuxではすべてのアイテムがファイルと見なされ、ディレクトリも考慮されるためです。例として、テキストエディタを使用して/ etc /を「開く」、つまり:nano -w/etc/nanoは、/ etc /がディレクトリであることを丁寧に教えてくれます。終わりのないシンボリックリンクを作成することは技術的に合法だからです。昔は、境界チェックが書かれる前に、/ etcという名前の2つのファイル(1つはファイル、もう1つはディレクトリ)を持つFHSシステムがあり、システムは違いを認識していました。

chromiumos開発者ガイド のハハノートを参照してください:

〜/ trunk内にchrootが再び見つかるため、ファイルシステムループがあります。これについてあまり長く考えないでください。 du -s $ {HOME}/chromiumos/chroot/homeを使用しようとすると、ファイルシステムが破損しているというメッセージが表示される場合があります。これは心配する必要はなく、コンピュータがこのループを理解していないことを意味します。 (このループを理解できる場合は、もっと難しいことを試してください。

あえて、もっと難しいものをクリックしてください:)ループを防ぐために、lnにはフルパスが必要です。

質問2は、manページをもう一度読むことで答えることができます。最後の文を見てください。

説明

   In the 1st form, create a link to TARGET with the name LINK_NAME.  In
   the 2nd form, create a link to TARGET in the current directory.  In
   the 3rd and 4th forms, create links to each TARGET in DIRECTORY.
   Create hard links by default, symbolic links with --symbolic.  By
   default, each destination (name of new link) should not already
   exist.  When creating hard links, each TARGET must exist.  Symbolic
   links can hold arbitrary text; if later resolved, a relative link is
   interpreted in relation to its parent directory.

Re:Edit: "しかし、コマンドの実行時に、ユーザーに計算を強制するのではなく、シェルがそのパスを解析できないのはなぜですか道が何であるかを見つけて、彼/彼女自身でそれを入力しますか?」


この例を考えてみましょう。アプリケーションAはライブラリバージョン1.0.aをインストールします。ライブラリAに依存するアプリケーションX、Y、Zをビルドします。アプリケーションAはバグを見つけて更新し、ライブラリを1.0.1.2.aとして保存します。アプリケーションX、Y、およびZは、1.0を1.0.1.2に直接置き換えるとライブラリ1.0を使用するため、破損しますが、バージョン1.0.1.2をバージョン1.0にシンボリックリンクすると、何も破損しません。

ln -s /usr/lib64/libfoo-1.0.1.2.a /usr/lib64/libfoo-1.0.a

また、アプリケーションX、Y、およびZは、適用されたライブラリから新しいバグ修正を取得します。これは、シェルが1.0から1.0.1.2へのリンクをたどるが、それを1.0と呼ぶためです。このような場合、システム全体の破損の可能性を高めるため、シェルがパスを想定することは望ましくありません。ところで、64ビットシステムでは/ usr/libは/ usr/lib64にリンクされています。これは、先ほど大規模に示した例を修正するためです。つまり、32ビットアプリケーションでは、ライブラリが/ usr/libにインストールされていることを想定しています。システムには純粋な32ビットライブラリがないため、/ usr/libは次のように/ usr/lib64にリンクされます。

ln -s /usr/lib64 /usr/lib
6
eyoung100

質問1:ソフトリンクの場合は両方のファイル/フォルダーのパス全体を書き出す必要があるのに、ハードリンクの場合はターゲットファイルのファイル名を省略できるのはなぜですか?

ターゲットが現在のディレクトリにない限り、ソフトリンクのパスやファイル名も指定する必要はありません。たとえば、ファイル_~/Downloads/target_file_がある場合、次のことができます。

_ln `~/Downloads/target_file`
_

_~/_にいるとき、ファイル名_~/Downloads/target_file_で_~/_の_target_file_へのハードリンクを作成します。することもできます

_ln -s `~/Downloads/target_file`
_

_~/_にいるとき、ファイル名_~/Downloads/target_file_で_~/_の_target_file_へのソフトリンクを作成します。

質問2:ソフトリンクのOLDファイル/フォルダーのファイルパスがその親を基準にしているのに、他の3つのパス(ハードリンクOLD、NEWファイル、ソフトリンクNEWファイル/フォルダー)がファイル/フォルダーを基準にしているのはなぜですか自分自身?

4つのパスはすべて、(現在のフォルダーに対して)相対パスでも絶対パスでもかまいません。唯一の基準は、名前またはパスを指定しない場合は、ハードリンクまたはソフトリンクを同じフォルダーに配置しないことです。

lnのマニュアルページ をお読みください。 Ubuntu 14.04でこれをすべて試しましたが、マニュアルページで確認されているので、OSについて心配する必要はありません。 OS固有ではありません。

2
jobin

ハードリンクを作成する場合、ソースパスはリンクの作成時に使用されるため、現在の作業ディレクトリからの相対パス(または絶対パス)である必要があります。シンボリックリンクを作成すると、ソースパスは文字列として扱われます。リンクが使用されるときに解釈されるため、リンクがあるディレクトリを基準にしています。

あなたの例を考えてみましょう。現在のディレクトリは/home/userです。

  • コマンドln -s new/file new2/fileは、テキストがnew/fileであるシンボリックリンクを作成し、このリンクをnew2/fileの場所に配置します。プログラムがそのリンクにアクセスするとき、ターゲットは存在しない/home/user/new2/new/fileです。
  • コマンドln -s ../new/file new2/fileは、テキストが../new/fileであるシンボリックリンクを作成し、このリンクをnew2/fileの場所に配置します。プログラムがそのリンクにアクセスするとき、ターゲットは/home/user/new2/../new/fileであり、これは/home/user/new/fileに短縮されます。
  • コマンドln new/file new2/fileは、new2/file(存在する必要があります)と同じファイルを指すディレクトリエントリを/home/user/new/fileの場所に作成します。

多くの場合、シンボリックリンクを作成する前にターゲットディレクトリに変更する方が混乱が少なくなります。

cd new2
ln -s ../new/file .