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

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

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

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

また、シンボリックリンクのターゲットパーティションをどのように見つけますか?別のパーティションにリンクされたファイルがあると仮定すると、そのソースファイルのパスをどのように見つけることができますか?

答え1

testJimの回答では、のテストを使用してシンボリックリンクをテストする方法について説明します-L

しかし、厳密に言えば、「ハードリンク」をテストすることは望むものではありません。ハードリンクの仕組みは、Unixがファイルを処理する方法によって異なります。各ファイルは inode で表されます。その後、単一のinodeにゼロ個以上の値があります。名前またはディレクトリエントリまたは技術的に言えば、ハードリンク(「文書」と呼ぶもの)。

幸いなことに、このstatコマンド(利用可能な場合)は、inodeにいくつの名前があるかを知らせることができます。

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

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

この-c '%h'ビットは、statinode のみに出力されるハードリンクの数、つまりファイル名の数を示します。-gt 1その後、1より大きいことを確認してください。

他のファイルと同様に、シンボリックリンクも複数のディレクトリに接続できるため、シンボリックリンクへのハードリンクが複数ある場合があります。

答え2

一例:

$ 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同じファイルです(同じinode:10802124、わかるようにリンク例3)。彼らは同じハードリンクです定期的な文書。

s4また、s5同じファイル(10802384)です。彼らはタイプに属しますシンボリックリンク、いいえ定期的な。彼らはここの道を指していますs3s4s5は同じディレクトリにあるエントリなので、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 ]。同様に、ファイルが通常のファイルの場合はtestを使用できますが、[ -f file ]その場合はシンボリックリンクが解決された後にスキャンが実行されます。

ハードリンクはファイルタイプではなく、ファイル(すべてのタイプ)の別の名前にすぎません。

リンク数を確認して、ファイルが複数のディレクトリに複数(ハード)リンクされていることを確認できます。

POSIX的に:

has_more_than_one_link() (
  export LC_ALL=C # only locale where the output of ls -n is specified
  export TZ=UTC0  # simplify the mtime field (which we don't need anyway)
                  # generation as an optimisation.
  unset -v IFS    # for default separator for read to include space and
                  # tab, the only 2 "blank" characters in the C/POSIX locale
  ls -nqd -- "$1" | {
    read -r ignore links ignore &&
      [ "$links" -gt 0 ]
  }
)

または以下を使用してzsh

has_more_than_one_link() () (($#)) $1(Nl+1)

関数本体は、基本(($#))本体が(パラメータ数が0より大きい場合はtrueを返す)匿名関数であり、パラメータはファイルへのリンク数が1より大きい場合にのみ$1(Nl+1)ワイルドカード文字の拡張です。$1、 に拡張される予定です。

またはstat内蔵機能を使用してください。

zmodload zsh/stat
has_more_than_one_link() {
  stat -LA2 +nlink -- "$1" && (( $2 > 1 ))
}

$2(別の変数を宣言する必要がないようにリンク数を保存します。地元の)。

一部のシステムには外部statコマンド(通常のコマンドより後zsh)がありますが、すべて異なるインターフェイスを持っていますzsh

GNU実装では、特別に呼び出されたファイルstatを処理する必要があります。これは、GNUはこれを-stdinでstat操作を実行することを意味すると解釈するからです。fstat()

has_more_than_one_link() {
  local nlink
  [ "$1" != - ] || set ./-
  nlink=$(stat -c %h -- "$1") &&
    [ "$nlink" -gt 1 ]
}

(これはPOSIXに似たシェルがスコープをサポートしていると local仮定します)。

答え3

コマンドの-hAND演算子を使用してください。-Ltest

-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

~によるとこのスレッド、動作は同じですが、-L優先されます。

答え4

ここには非常に正確な答えがたくさんありますが、元の誤解を実際に解決した人は誰もいないと思います。元の質問は基本的に「シンボリックリンクを作成すると後で識別するのは簡単ですが、ハードリンクを識別する方法がわかりません。」でした。はい、答えは基本的に「できません」として帰結します。以下の理由を説明しますが、実際にはそれが混乱して奇妙だという事実を誰も認めないようです。

これらすべてを読んで、すでに何が起こっているのかを知っていれば、私の記事を読んでいる必要はありません。それでも混乱している場合は、続行してください。

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

オペレーティングシステムするただし、同じファイルを指す異なる項目の数を追跡する必要があります。 Wilma.txtを削除してもドライブスペースが確保されないことは驚くべきことではありません。ただし、Fred.txt(「オリジナル」ファイル)を削除しても、ドライブのFred.txtというデータは依然としてBarney.txtなので、ドライブの容量を確保できません。削除する場合のみみんなディレクトリエントリの数により、オペレーティングシステムはデータ自体が占めるスペースを割り当て解除します。

Barney.txtがシンボリックリンクの場合は、Fred.txtを削除してください。会議スペースの割り当てがキャンセルされ、Barney.txt が壊れたリンクになりました。また、シンボリックリンクが指すファイルを移動したり名前を変更したりすると、リンクが壊れます。ただし、ハードリンクファイルは、そのファイル/データを指す他のディレクトリエントリを破損することなく、自由に移動したり名前を変更したりできます。なぜなら、そのファイル/データはすべてドライブの同じデータブロックを参照するディレクトリエントリであるからです(対応するデータのinode番号を使用)。 。

[2年後、最後は少し混乱します。ちょっと待ってください。明確にしなければならないと思いました。 「mv ./Wilma.txt ../elsewhere/Betty.txt」と入力すると、ファイルを移動するように見えますが、実際にはそうではありません。実際に行っていることは、現在のディレクトリのディレクトリリストから、「'Wilma.txt'という名前はinode ######"#を使用して見つけることができるデータに関連付けられています」という行エントリを削除して報告しますということです。 2のように移動できる理由です。KBファイルを同じドライブ上の他の場所にできるだけ早く移動できます。

オペレーティングシステムは、同じデータブロックを指す異なるディレクトリエントリの数を追跡する必要があるためできる表示しているディレクトリエントリが「元の」ディレクトリエントリであるかどうかわからない場合でも、特定のファイルがハードリンクされていることを確認してください。 1つの方法は、「ls」コマンド、特に「ls -l」(つまり、ダッシュの後の小文字のL)です。

前の例を借りて...

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

最初の文字はダッシュなので、ディレクトリや奇妙なものではなく、「一般」の一般的なファイルです。しかし、それが本当に普通の場合、「このデータブロックを指すディレクトリエントリがあります」のように、rwx-ish部分の後の数字は「1」になります。ただし、これはハードリンクデモの一部なので、「3」と表示されます。

これは奇妙で不思議な動作を引き起こす可能性があります(ハードリンクを真剣に受け入れない場合)。テキストエディタでFred.txtを開き、いくつかの変更を加えると、Wilma.txtとBarney.txtでも同じ変更が表示されますか?おそらく。おそらく。テキストエディタがソースファイルを開き、変更を記録して変更を保存すると、3つの名前はすべて同じ(新しく変更された)テキストを指します。ただし、テキストエディタが新しいファイル(Fred-new-temp.txt)を作成し、変更されたバージョンをそのファイルに書き込み、Fred.txtを削除してFred-new-temp.txtの名前をFred.txtに変更すると、WilmaとBarneyは、新しく変更されたバージョンではなく元のバージョンを指します。ハードリンクを理解していない場合は、少し怒るかもしれません。 :) [まあ、私は個人的に実際には1つも知らない。テキストエディタこれは新しいファイル/名前変更操作を実行しますが、まさにそのタスクを実行する他のプログラムをたくさん知っているので注意してください。 ]

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

関連情報