以下の様なディレクトリ構造がある場合を考える。
$ 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 -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 |
1 | 1 |
以下の場合、デッドリンクだけが返される。上と結果は同じだが意味は異なる。-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 . | -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 |
0 | 0 | 1 |
少し無駄があるものの、以下のようにすることでデッドリンクと循環リンクの両方を検索することが可能。ファイルテスト演算子を使ってファイルが存在するかを判定している。
$ find . -type l -exec test ! -e {} \; -print ./cycliclink ./deadlink $ echo $? 0
$ 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 |
0 | 0 | 0 |
_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