綾小路龍之介の素人思考

[linux] find で壊れたシンボリックリンクを探す

ここで言う「壊れた」シンボリックリンクとは、存在しないファイルへのリンク (デッドリンク) と循環参照しているリンク (循環リンク) を指すものとする。注意すべきは、むやみに削除してはいけない壊れたシンボリックリンクがあるということだ。例えば chroot されるディレクトリには親システムから見れば壊れたリンクが有るものの、chroot システムでは意味を持つリンクがある。

以下の様なディレクトリ構造がある場合を考える。

$ ls -laR
.:
total 20
drwxr-xr-x  3 **** ****  4096 Oct 14 06:13 .
drwxr-xr-x 28 **** **** 12288 Oct 14 06:13 ..
lrwxrwxrwx  1 **** ****    10 Oct 14 04:53 cycliclink -> cycliclink
lrwxrwxrwx  1 **** ****    12 Oct 14 04:57 deadlink -> removed-file
drwxr-xr-x  2 **** ****  4096 Oct 14 07:00 dir
-rw-r--r--  1 **** ****     0 Oct 14 04:56 file
lrwxrwxrwx  1 **** ****     3 Oct 14 06:13 link-to-dir -> dir
lrwxrwxrwx  1 **** ****     4 Oct 14 05:22 link-to-file -> file

./dir:
total 8
drwxr-xr-x 2 **** **** 4096 Oct 14 07:00 .
drwxr-xr-x 3 **** **** 4096 Oct 14 06:13 ..
-rw-r--r-- 1 **** ****    0 Oct 14 05:21 file

以下の場合、デッドリンクだけが返される。-L オプションはシンボリックリンクのリンク先を再帰的に辿りその情報を参照するが、リンク先が存在しない場合 (デッドリンク) はシンボリックリンクの情報を判別式に渡す。このため -type l 判別式でデッドリンクを評価すると true が返る。また、-L オプションでリンク先の参照が終わらない場合 (循環リンク) は判別式に渡る前にエラー。find の終了ステータスはエラーが起きた場合の 1 を返している。この方法はデッドリンク ("broken symbolic links") を探す方法としてマニュアルに書いてある。

$ find -L . -type l
find: `./cycliclink': Too many levels of symbolic links
./deadlink
$ echo $?
1
find で発見されるファイルの比較
$ find -L .-type l
..
./link-to-file./link-to-file
./cycliclink
./link-to-dir./link-to-dir
./link-to-dir/file./link-to-dir/file
./dir./dir
./dir/file./dir/file
./file./file
./deadlink./deadlink./deadlink
11

以下の場合、デッドリンクだけが返される。上と結果は同じだが意味は異なる。-P オプションが有効 (デフォルト、シンボリックリンクのリンク先を辿らない) なので、-type l 判別式でシンボリックリンクを評価すると true が返る。-xtype l 判別式でシンボリックリンクを評価すると、リンク先を再帰的に辿りその情報を参照される、リンク先が存在しない場合 (デッドリンク) はシンボリックリンクの情報が使われるため、-xtrue l 判別式は true を返す。リンク先の参照が終わらない場合 (循環リンク) は判別式に渡る前にエラー。find の終了ステータスはエラーが起きた場合の 1 を返している。

$ find . -type l -xtype l
find: `./cycliclink': Too many levels of symbolic links
./deadlink
$ echo $?
1
find で発見されるファイルの比較
$ find .-type l-xtype l
..
./link-to-file./link-to-file./link-to-file
./cycliclink./cycliclink./cycliclink
./link-to-dir./link-to-dir./link-to-dir
./link-to-dir/file
./dir./dir
./dir/file./dir/file
./file./file
./deadlink./deadlink./deadlink./deadlink
001

少し無駄があるものの、以下のようにすることでデッドリンクと循環リンクの両方を検索することが可能。ファイルテスト演算子を使ってファイルが存在するかを判定している。

$ find . -type l -exec test ! -e {} \; -print
./cycliclink
./deadlink
$ echo $?
0
find で発見されるファイルの比較
$ find .-type l-exec test ! -e {} \; -print
..
./link-to-file./link-to-file./link-to-file
./cycliclink./cycliclink./cycliclink./cycliclink
./link-to-dir./link-to-dir./link-to-dir
./link-to-dir/file
./dir./dir
./dir/file./dir/file
./file./file
./deadlink./deadlink./deadlink./deadlink
000

_POSIX_SYMLOOP_MAX

$ find . -type l -printf '%Y\0%p\0' | xargs -0 -r -n2 sh -c 'if [ $0 = N -o $0 = L ]; then /bin/echo -ne $1\\0; fi' | xargs -0 -r -n1 /bin/echo

リファレンス

  1. How to find "dead" symbolic links ?
  2. Pub/UnixCommandEquivalents - ynform
  3. Find broken symlinks | commandlinefu.com
  4. unix - How do I find and report on broken symbolic links automatically? - Server Fault
  5. command line - How can I find broken symlinks - Unix & Linux Stack Exchange
  6. Symbolic Links - Finding Files
  7. Pub/FindBrokenSymbolicLinks - ynform
  8. Linux find and remove all symlinks relating to a directory - Unix & Linux Stack Exchange
  9. Pub/FindCommandDetectUnixCyclicSymbolicLink - ynform
  10. How to find broken symbolic links - a great resource for How To's from Wikia
  11. The Otomaton Blog | Linux Shell Scripting & Automation | Page 6
  12. シンボリックリンクのループの検知方法について教えてください。.. - 人力検索はてな

ソーシャルブックマーク

  1. はてなブックマーク
  2. Google Bookmarks
  3. del.icio.us

ChangeLog

  1. Posted: 2010-08-16T15:01:50+09:00
  2. Modified: 2010-08-16T15:01:50+09:00
  3. Generated: 2017-04-14T23:09:17+09:00