ファイルがハードリンクかシンボリックリンクかを判断しますか?


51

ファイルへのファイル名/パスを取得し、ファイルがシンボリックリンクかハードリンクかを判断するシェルスクリプトを作成しています。

唯一のものは、それらがハードリンクかどうかを確認する方法がわかりません。テストファイルとして使用するために、ハードリンクとシンボリックリンクの2つのファイルを作成しました。しかし、ファイルがハードリンクであるか、シェルスクリプト内のシンボリックであるかをどのように判断しますか?

また、シンボリックリンクの宛先パーティションを見つけるにはどうすればよいですか?別のパーティションにリンクするファイルがあるとしましょう。元のファイルへのパスをどのように見つけますか?


16
ハードリンクとはどういう意味ですか?すべてのファイルはハードリンクです。
テルドン

1
@terdon ln /foo/bar/ /foo/bar2はハードリンクをln -s /foo/bar /foo/bar2作成し、symlink を作成します。
DisplayName 14年

14
@DisplayNameはい、ただしすべてのファイルはiノードへのハードリンクです。これがLinuxファイルシステムの仕組みです。あなたの例では、bar2barちょうど同じiノードを指して、両方のハードリンクされています。
テルドン

10
@DisplayNameはい、他のiノードへのハードリンクです。ここに矛盾はありません。ファイルはiノードへのリンクです。これがファイルの定義です。あなたの場合、これらのリンクは別の場所にありますが、基礎となるデータ構造は変わりません。私のポイントは、両方のことであるbarbar2同様に重要です。一方は他方へのリンクではなく、両方ともリンクですが、同じiノードを指します。
テルドン

3
@Scottいいえ、通常のファイルはハードリンクであり、作成されたハードリンクは通常のファイルと同じであると言っていlnます。
テルドン

回答:


42

ジムの答えは、シンボリックリンクをテストする方法を説明します:test-Lテストを使用して。

しかし、「ハードリンク」のテストは、厳密に言えば、あなたが望むものではありません。ハードリンクは、Unixがファイルを処理する方法が原因で機能します。各ファイルは単一のiノードで表されます。次に、単一のiノードには、0個以上の名前またはディレクトリエントリ、または技術的にはハードリンク(「ファイル」と呼んでいるもの)があります。

ありがたいことに、statコマンドは、可能な場合は、iノードにいくつの名前があるかを教えてくれます。

したがって、あなたはこのようなものを探しています(ここではGNUまたはbusyboxの実装を想定していますstat):

if [ "$(stat -c %h -- "$file")" -gt 1 ]; then
    echo "File has more than one name."
fi

この-c '%h'ビットはstat、iノードへのハードリンクの数、つまりファイルの名前の数だけを出力するように指示します。-gt 1次に、それが1より大きいかどうかを確認します。

他のファイルと同様に、シンボリックリンクも複数のディレクトリにリンクできるため、1つのシンボリックリンクに複数のハードリンクを設定できます。



@ k-Rockerはい。次に、パーティションのどこかに2番目の名前が付けられます。
デロバート14年

1
OS Xや* BSDで、それはですstat -f %l /path/to/file。またgstat -c %h /path/to/file、GNU coreutilsをデフォルト名なしで(OS XでHomebrewを使用して)インストールした場合にも使用できます。
GDP2

29

例:

$ touch f1
$ ln f1 f2
$ ln f1 f3
$ ln -s f1 s1
$ ln -s f2 s2
$ ln -s ./././f3 s3
$ ln -s s3 s4
$ ln s4 s5
$ ls -li
total 0
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 f1
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 f2
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 f3
10802345 lrwxrwxrwx 1 stephane stephane 2 Nov 12 19:56 s1 -> f1
10802346 lrwxrwxrwx 1 stephane stephane 2 Nov 12 19:56 s2 -> f2
10802347 lrwxrwxrwx 1 stephane stephane 8 Nov 12 19:56 s3 -> ./././f3
10802384 lrwxrwxrwx 2 stephane stephane 2 Nov 12 19:56 s4 -> s3
10802384 lrwxrwxrwx 2 stephane stephane 2 Nov 12 19:56 s5 -> s3

f1f2およびf3ディレクトリエントリは、同じファイル(同じiノード:10802124、あなたは数気づくあるリンクは 3です)。これらは、同じ通常ファイルへのハードリンクです。

s4そしてs5また、同じファイル(10802384)です。それらはタイプシンボリックリンクであり、通常ではありません。ここでパスを指しますs3s4およびs5は同じディレクトリのエントリであるため、その相対パスs3は両方の同じファイル(inod 10802347のファイル)を指します。

を実行するとls -Ll、シンボリックリンクを解決した後にファイル情報を取得するよう求められます:

$ ls -lLi
total 0
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 f1
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 f2
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 f3
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 s1
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 s2
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 s3
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 s4
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 s5

これらはすべて同じファイル(10802124)に解決されることがわかります。

を使用して、ファイルがシンボリックリンクかどうかを確認できます[ -L file ]。同様に、ファイルが通常のファイルであるかどうかをテストできます[ -f file ]が、その場合、チェックはシンボリックリンクの解決後に行われます。

ハードリンクはファイルの種類ではなく、ファイル(別の種類の)の異なる名前です。


19

コマンドの-hand -L演算子を使用test

-h file 
true if file is a symbolic link

-L file 
true if file is a symbolic link

http://www.mkssoftware.com/docs/man1/test.1.asp

このSOスレッドによると、それらは同じ動作をしますが、-L推奨されます。


わかりましたが、ハードリンクはどうですか?トレッドをチェックしましたが、ハードリンクについては何もしませんでした。-Lがfalseを返す場合、それはハードリンクを意味していますか?または単に通常のファイル?
kロッカー

1
ハードリンクは同じを共有しinodeます。また、出力lの先頭にソフトリンクが表示されls -lます...これらのルールをスクリプトにまとめて[[ -L file ]]、特定のファイルがsoftまたはhardのいずれであるかをテストすることができると思います。
jimm-cl

わかりました、また、シンボリックリンクの宛先パーティションを見つけるにはどうすればよいですか?
kロッカー

3

ここには非常に正しい答えがたくさんありますが、元の誤解に実際に取り組んだ人はいないと思います。元の質問は基本的に「シンボリックリンクを作成すると、後で簡単に識別できます。しかし、ハードリンクを識別する方法がわかりません」です。そして、はい、答えは基本的に「できない」に要約され、多かれ少なかれその理由を説明しますが、実際、それは混乱し、奇妙です。

これをすべて読んでいて、何が起こっているのかを理解していれば、あなたは大丈夫です。あなたは私の少しを読む必要はありません。まだ混乱している場合は、続けてください。

本当に短い答えは、ハードリンクは実際にはリンクではなく、シンボリックリンクのようではないということです。これは、元のディレクトリエントリと同じバイトの束を指すディレクトリ構造内の新しいエントリであり、一度作成すると、最初のエントリと同じように「本物」で正当なものになります。ドライブ上のすべての「通常の」ファイルには、少なくとも1つのハードリンクがあります。それなしでは、あなたはそれを見ることはありませんディレクトリ、およびそれを参照したり使用したりすることはできません。したがって、ファイルFred.txtがあり、Wilma.txtとBarney.txtをそのファイルにハードリンクすると、3つの名前(およびディレクトリエントリ)はすべて同じファイルを参照し、すべて同じように有効です。OSが、テキストエディタで「保存」を押したときにエントリの1つが作成され、他のエントリが「ln」コマンドで作成されたことを通知する方法はありません。

ただし、OS 同じファイルを指している異なるエントリの数を追跡する必要があります。Wilma.txtを削除しても、ドライブの空き領域が確保されないのは当然のことです。ただし、Fred.txt(「元の」ファイル)を削除しても、ドライブの空き領域は確保されません。これは、Fred.txtというドライブ上のデータもBarney.txtのままであるためです。すべてのディレクトリエントリを削除た場合にのみ、OSはデータ自体が占有していたスペースの割り当てを解除します。

Barney.txtがシンボリックリンクされていた場合は、Fred.txtを削除してしまうデ割り当てられたスペースを持っている、とBarney.txtは現在、リンク切れになります。また、それを指すシンボリックリンクを持つファイルを移動または名前変更すると、リンクが解除されます。ただし、ハードリンクされたファイルは、そのファイル/データを指す他のディレクトリエントリを壊すことなく、すべて移動または名前変更できます。これらはすべて、ドライブ上の同じデータブロックを参照するディレクトリエントリであるためですそのデータのiノード番号)。

[それは2年後、その最後の少し混乱しいたので、明確にすると思います。「mv ./Wilma.txt ../elsewhere/Betty.txt」と入力すると、ファイルを移動しているように見えますが、実際はそうではありません。実際に行っているのは、現在のディレクトリのディレクトリリストから行項目を削除することです。「Wilma.txt」という名前は、iノード######を使用して検索できるデータに関連付けられています。 #、」と新しい行項目をディレクトリ../elsewhereのディレクトリリストに追加し、「名前 'Betty.txt'はiノード#######で検索できるデータに関連付けられています」と表示します。これが、同じドライブ上の別の場所に移動している限り、2ギガバイトのファイルを2キロバイトのファイルと同じ速さで「移動」できる理由です。]

OSは、データの同じチャンクを指しているどのように多くの異なるディレクトリエントリを追跡する必要があるため、あなたがすることができ、特定のファイルをハードにリンクされている場合は、確実に伝えることができないにもかかわらず、伝える場合、そのディレクトリエントリ「見ているのは、「オリジナル」なのかどうか」1つの方法は、「ls」コマンド、具体的には「ls -l」(ダッシュの後の小文字のL)です。

以前の例を借りるには...

 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 f1

最初の文字はダッシュなので、ディレクトリや他のエキゾチックなものではなく、「通常の」通常のファイルです。しかし、本当に普通であれば、「このデータブロックを指すディレクトリエントリが1つあります」のように、rwx-ish部分の後の数字は「1」になります。しかし、これはハードリンクのデモの一部であるため、代わりに「3」と表示されます。

これは、奇妙で神秘的な動作につながる可能性があることに注意してください(ハードリンクに頭を包んでいない場合)。テキストエディターでFred.txtを開いて変更を加えた場合、Wilma.txtとBarney.txtにも同じ変更が表示されますか?多分。恐らく。テキストエディタが元のファイルを開いて変更を書き込むことで変更を保存する場合、はい、3つの名前はすべて同じ(新しく変更された)テキストを指します。ただし、テキストエディターが新しいファイル(Fred-new-temp.txt)を作成し、変更されたバージョンをそのファイルに書き込み、Fred.txtを削除し、Fred-new-temp.txtの名前をFred.txtに変更すると、ウィルマとバーニーは新しく変更されたバージョンではなく、元のバージョンを引き続き指している。ハードリンクを理解していない場合、これは少し怒ってしまう可能性があります。:) [わかりました、私は実際に個人的に知りません新しいファイル/名前の変更を行うテキストエディターですが、それを正確に行う他の多くのプログラムを知っているので、注意してください。]

最後の注意: 'fsck'(ファイルシステムチェック)がチェックすることの1つは、何らかの方法でディレクトリエントリによって参照されなくなったデータブロックがドライブにあるかどうかです。時々何かがおかしくなり、inodeを指す唯一のディレクトリエントリが削除されますが、ドライブスペース自体は「使用可能」としてマークされません。fsckの仕事の1つは、割り当てられたすべてのスペースをすべてのディレクトリエントリと照合して、参照されていないファイルがないことを確認することです。見つかった場合、新しいディレクトリエントリを作成し、「lost + found」に入れます。


ただ疑問に思うのは、それらの「まさにそれを行う他のプログラム」とは何なのでしょうか?
phk

@phk彼が具体的に何を考えているのかわからないが、それは長い時間がかかり、失敗すると不確実な状態に陥るアクションを行うための一般的なアプローチです。たとえば、リモートサーバーからダウンロードしようとして、サーバーがタイムアウトする可能性があることがわかっている場合、1つの方法はコンテンツ全体を一時ファイルにダウンロードすることです。そうすれば、ダウンロードに問題が発生した場合でも、元のファイルが残っています。
cwallenpoole

私が確実に知っている唯一のプログラムはFreeHandです。保存中にクラッシュした場合、元のファイルが壊れているのではなく、一時ファイルが残っているためです。しかし、私は他のプログラムもそれを見ています。現時点では具体的な例を挙げることはできません。
Snarke

2

使用できますreadlink FILE; echo $?。これは、ハードリンクの場合は1を返し、シンボリックリンクの場合は0を返します。

manページから:「readlinkとして呼び出されると、シンボリックリンクのターゲットのみが出力されます。指定された引数がシンボリックリンクでない場合、readlinkは何も出力せず、エラーで終了します。」

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.