検索とシンボリックリンク

検索とシンボリックリンク

コマンドの使い方に関するより良いアイデアを得るために、findに関するドキュメントを見つけました。

私が読んでいる部分はこう言います。

GNU find は、2 つの方法のいずれかでシンボリックリンクを処理します。まず、リンクを逆参照できます。つまり、シンボリックリンクを検出すると、リンクが指すファイルを調べて、指定した基準を満たしていることを確認します。次に、実際のリンクを探している場合は、リンク自体を確認できます。 findコマンドを使用して取得したディレクトリ階層内のファイルをシンボリックリンクが指す場合、2つの方法の間に大きな違いがない可能性があります。

デフォルトでは、findはシンボリックリンクを見つけたらそれ自体をチェックします(そして、後でリンクされたファイルが見つかるとリンクもチェックします)。

私が理解しているように、次のようなことをした場合:

find -L -iname "*foo*"

これは現在のディレクトリを再帰的に検索し、シンボリックリンクが見つかると元のファイルへのリンクに沿って検索します。元のファイル名がパターンの場合、前のリンクが*foo*報告されます。

しかし、これは本当ではないようです。私は持っています

main-file
sl-file -> main-file

上記のコマンドを実行すると報告さfind -L -iname "*main*"れます。

./main-file

楽しみにしています

./main-file # because it matches the criterion
./sl-file   # because the file points to matches the criterion

つまり、別のテストを使用すると、期待-typeどおりに機能します。私がこれを持っているとしましょう:

main-file
dir/sl-file -> ../main-file

これを実行

find dir -type f

何も返しません。しかし、これは

find -L dir -type f

レポートdir/sl-file

何を提供しますか?

私はすでに経験したこの投稿これは、ファイル名がファイル属性ではないことを意味します。これは本当に理解できないことです。

ベストアンサー1

Gnufind文書は用語では似ていません。POSIXワン。後者は要点を説明し、私はそれに言及します。定義されていない-inameので、これに焦点を当てます。大文字と小文字を区別せずに同様に設計されていると-name思います。したがって、私はそのすべての属性が適用可能なケースから独立していることを望みます。-iname-name-name-iname

POSIX 文書の関連部分は次のとおりです。

find [-H|-L] path... [operand_expression...]
このユーティリティは[… ]で指定された各ファイルで、ディレクトリ階層を繰り返しダウンさせる必要がfindあります。末尾の<スラッシュ>文字を含むpathpathオペランドは、指定されたとおりに評価されます。階層で見つかった他のファイルへのすべてのパス名は、現在のパスオペランド(現在のパスオペランドが1で終わらない場合は<スラッシュ>)として評価されます。パスオペランドに基づいてファイル名を連結します。反対の部分にはドットまたはドット - コンポーネントを含めないでください。末尾の<スラッシュ>文字も含めないでください。パス名コンポーネントの間には単一の<スラッシュ>文字のみを含める必要があります。

-name pattern
現在のパス名の基本名がパターンマッチング表記を使用して一致する場合、pattern基本用語はtrueと評価する必要があります[...]

-print
[...] 現在のパス名が標準出力に書き込まれます。

そして定義:

basename
1つ以上のファイル名を含むパス名の場合:パス名の最後または唯一のファイル名。 [… ]

ファイル名
ファイル名を指定するために使用される一連のバイト[...]。名前を構成するバイトには <NUL> または <slash> 文字を含めることはできません。 [...] ファイル名は「パス名コンポーネント」とも呼ばれます。 [… ]

パス名
ファイルを識別するために使用される文字列。 [...]オプションの開始<スラッシュ>文字が続き、その後に<スラッシュ>文字で区切られた0個以上のファイル名が続きます。

したがって、-name現在のパス名の最終ファイル名に興味があります。現在のパス名は、現在のファイルを識別する文字列です。誰によって使用されますか?この場合、findパス名は概念的にファイルシステムの名前とは関係がない可能性があります。find特定の文字列がファイルを識別するために使用される場合、その文字列は「パス名」と呼ばれ、-name使用されます。

呼び出しfind . -printまたはfind -L . -print。この特定の呼び出しに使用されたすべてのパス名が表示されますfind。 .-name-name


main-fileとを使用した例では、コマンドはsl-fileですfind -L -iname "*main*"-print最後に、あなたが観察した結果は次のとおりです-print

./main-file # because it matches the criterion
./sl-file   # because the file points to matches the criterion

ただし、そうであれば、-printこれはandが与えられたことを意味するので、これは正確なパス名であり、したがっておよびは処理する対応するデフォルト名(または)です。./main-file./sl-filemain-filesl-file-name-iname

これは不適切です。これらのデフォルト名の1つだけを使用するパターン()と一致します*main*。そのため、結果は1つしか得られません。-name "*main*"(または)を指定し-iname "*main*"て発生を予測することは、一致を./sl-file予測するのと同じです。sl-file*main*

これは作る一部その気持ちは./main-file二度起こると予想されます。ただし、シンボリックリンクはfind2番目のパス名をからに変更し./sl-fileます./main-file。これにより、両方のパス名が一致し、両方*main*として印刷されます./main-file。これは起こりません。

これが必要な場合は、シンボリックリンクをbar指して配置することを検討してください。私たちはディレクトリにあります。何を印刷する必要があります(除く)?このパス名がテストに合格したいと思うので、デフォルト名は必要です。一方、規則に応じて、パス名は(提供されたパスと同様に)で始まり、ポイントコンポーネントを含めないでください。使用できる正常で意味のあるパス名はありません。何をすべきか?幸い、この場合、ツールはパス名である.を印刷し、文字列として。/etc/fstab/tmp/foo/foofind -L ..-name fstabfstab./../barfstab


シンボリックリンクを使用しないが-name動作する方法を示すいくつかの例:

  1. cd /etc && find . -name . 2>/dev/null

    .これは、「実際の」(ファイルシステムの特定の)名前があるという事実にもかかわらず、etc場合によってはディレクトリが存在する可能性がありますが、サブディレクトリを見つけることはできません.

  2. cd /etc && find . -name etc 2>/dev/null

    etc見つけることもできません.

  3. 空のFAT32ファイルシステムを作成し、それをcdマウントポイントにマウントします。ファイルシステムは大文字と小文字を区別せず、Linuxはこれを認識しています。aファイルシステムに名前付きファイルを作成します。次のように実験してみてください。

    • $ find .
      .
      ./a

      aこの場合、ツールは特定の時点でファイルシステムからそれをインポートする必要があります。

    • $ find a
      a
      $ find A
      A

      この場合、ツールはコマンドライン引数を使用またはa取得します。Aファイルシステムはそのようなファイルが存在することを確認するだけです。ファイルシステム(およびオペレーティングシステム)は、この特定のファイルaまたはA

    • $ find a -name A
      $ find A -name a

      何もない!これは-name、ファイルシステムがファイルについて何を知っているかは関係ありません。使用されているパス名のみがfind重要です。

      あなたの例と同様のことは、-inameファイルシステムがシンボリックリンクとそのターゲットについて何を知っているのか気にしないことです。使用されているパス名のみがfind重要です。


何が起こっているのかを明確にするために、次のディレクトリ構造を使用して例に戻ります。

.
├── main-file
└── sl-file -> main-file

find . -printまたはfind -L . -print印刷:

.
./main-file
./sl-file

これはパス名です。ひも find3つを識別するために使用されます文書(ディレクトリも文書)。文字列は.コマンドからのもので、残りの2つは.確認(文字列ではなくファイルを意味します)、ディレクトリタイプの理解、子孫の決定(サポートされている場合は一般的に考慮されます-prune-maxdepth、および内容のリストを介して作成されますmain-filesl-file

この文字列は、/.sl-file識別するファイルに対して操作が実行される前に構成されます。この文字列は、ファイルに対して操作を実行するためにfind必要です。

ただし、ファイルに対して何もしません。そのデータやメタデータは必要ありません-name-print彼らはパス名を使用します。ひも

パス名を評価するとき、-name "*main*"そのファイルまたはファイルシステム全体はまったく関係ありません。関連する唯一のものはパス名です。ひも;より具体的に言えば、最後のコンポーネントであるデフォルト名も次のようになります。ひも

特定のパス名にそのパスを-name使用したのか-L、ファイルが最初にシンボリックリンクであるのか、指す場所であるのか、破損していないのかは重要ではありません。それは知られていると関係がありますひも

一方、ファイルシステムクエリに似ている-typeか、クエリが必要なテストは-mtime文書パス名で識別されます。文字列では十分ではありません。シンボリックリンクの場合は、-Lシンボリックリンクの宛先を照会するか、シンボリックリンク自体を照会するかを決定します。ただし-print、関連する場合は、クエリの内容に関係なくパス名を印刷します。

言い換えれば:

  • いいえ-L

    • ./main-file ひも識別する./main-file 文書タイプf
    • ./sl-file ひも識別する./sl-file 文書タイプl
  • そして-L

    • ./main-file ひも識別する./main-file 文書タイプf
    • ./sl-file ひもまだ確認済み./main-file 文書タイプf

次に、パス名(文字列)に適用されるテストまたはタスクと、ファイルに適用されるテストまたはタスクを記録する必要があります。

-name-printパス名を使用するため、find . -name "*main*"有無にかかわらず-L印刷されます。

./main-file

-typeファイルで機能するため、find . -type fパス名が印刷されます。

./main-file

両方のパス名を印刷しますfind -L . -type f

./main-file
./sl-file

おすすめ記事