壊れたシンボリックリンクを見つけるにはどうすればよいですか


282

指し示していないすべてのシンボリックリンクを見つける方法はありますか?

find ./ -type l

はすべてのシンボリックリンクを提供しますが、どこかに行くリンクとそうでないリンクを区別しません。

私は現在やっています:

find ./ -type l -exec file {} \; |grep broken

しかし、私はどのような代替ソリューションが存在するのかと思っています。

回答:


351

タスクには使用しないことを強くお勧めfind -Lします(説明については以下を参照)。これを行う他の方法は次のとおりです。

  • 「純粋なfind」メソッドを使用する場合は、次のようになります。

    find . -xtype l
    

    xtype参照解除されたリンクで実行されるテストですfind)ただし、これはのすべてのバージョンで利用できるわけではありません。しかし、他のオプションもあります:

  • コマンドtest -e内から実行することもできますfind

    find . -type l ! -exec test -e {} \; -print
    
  • いくつかのgrepトリックでさえ、よりも優れている(つまり、より安全です)がfind -L、質問(ファイル名を含む出力行全体を把握する)に示されているような正確なものではありません。

     find . -type l -exec sh -c 'file -b "$1" | grep -q ^broken' sh {} \; -print
    

find -L引用されたトリックソロでからCommandLineFuでは素晴らしく、ハックに見えますが、それは1つの非常に持っている危険な落とし穴を:すべてのシンボリックリンクが続いています。以下に示す内容のディレクトリを検討してください。

$ ls -l
total 0
lrwxrwxrwx 1 michal users  6 May 15 08:12 link_1 -> nonexistent1
lrwxrwxrwx 1 michal users  6 May 15 08:13 link_2 -> nonexistent2
lrwxrwxrwx 1 michal users  6 May 15 08:13 link_3 -> nonexistent3
lrwxrwxrwx 1 michal users  6 May 15 08:13 link_4 -> nonexistent4
lrwxrwxrwx 1 michal users 11 May 15 08:20 link_out -> /usr/share/

find -L . -type lそのディレクトリで実行する場合、すべて/usr/share/も検索されます(そして、それは本当に長い時間がかかる可能性があります)1「発信リンクに耐性がある」コマンドの場合は、find使用しないでください-L


1これはささいな不便さのように見えるかもしれません(コマンドはすべてを横断するのに「ちょうど」時間がかかります/usr/share)-より深刻な結果をもたらす可能性があります。たとえば、chroot環境を考えてみましょう。これらはメインファイルシステムのサブディレクトリに存在し、絶対的な場所へのシンボリックリンクを含むことができます。これらのリンクは、「外部」システムでは壊れているように見える場合があります。これは、chrootに入ると適切な場所を指すだけだからです。また、一部のブートローダー/bootは、ブートパーティションがとしてマウントされた最初のブートフェーズでのみ意味のあるシンボリックリンクを使用したことを思い出します/

したがって、find -Lコマンドを使用して、破損していないシンボリックリンクを無害なディレクトリから見つけて削除すると、システムが破損する可能性があります...


11
非リンク上で動作するため、-type l冗長だと思います。だから、おそらくあなたが必要とするすべてです。このアプローチをありがとう。-xtype l-type lfind -xtype l
-quornian

3
これらのソリューションは、すべてのファイルシステムタイプで機能するわけではないことに注意してください。たとえば、/proc/XXX/exeリンクが壊れているかどうかを確認するためには機能しません。これには、を使用しますtest -e "$(readlink /proc/XXX/exe)"
-qwertzguy

2
@Flimm find . -xtype lは、「(最終)ターゲットファイルがシンボリックリンクであるすべてのシンボリックリンクを検索する」という意味です。しかし、シンボリックリンクの最終的なターゲットはシンボリックリンクにすることはできません。そうしないと、リンクをたどることができ、最終的なターゲットではありません。そのようなシンボリックリンクはないので、それらを別の何か、つまり壊れたシンボリックリンクとして定義できます。
弱い

2
@JoóÁdám「壊れた場合にのみシンボリックリンクになります」。「壊れたシンボリックリンク」または「存在しないファイル」に個々のタイプを与えると、オーバーロードするのlではなく、混乱が少なくなります。
弱い

3
最後の警告は役に立ちますが、これは-Lハックには適用されず、壊れたシンボリックリンクを一般的に(ブラインドで)削除することに注意してください。
アロイスマーダル16

38

http://www.ibiblio.org/pub/Linux/utils/file/symlinks-1.4.tar.gzsymlinksコマンドを使用して、さまざまな特性を持つシンボリックリンクを識別することができます。例えば:

$ rm a
$ ln -s a b
$ symlinks .
dangling: /tmp/b -> a

このツールはosxで利用できますか?
2014

気にしないで、コンパイルしてください。
2014

2
どうやらsymlinksFedoraにプリインストールされています。
ダニエルジョンソン

32

rozcietrzewiaczがすでにコメントしているようにfind -L、検索をシンボリックリンクされたディレクトリに展開すると予期しない結果になる可能性があるため、最適なアプローチではありません。誰もまだ言及していないのは

find /path/to/search -xtype l

より簡潔で、論理的に同一のコマンドです

find /path/to/search -type l -xtype l

これまでに提示された解決策のいずれも、別のタイプの破損であるサイクリックシンボリックリンクを検出しません。 この質問は移植性に対処します。要約すると、循環リンクを含む壊れたシンボリックリンクを見つけるポータブルな方法は次のとおりです。

find /path/to/search -type l -exec test ! -e {} \; -print

詳細については、この質問またはynform.orgを参照してください。もちろん、これらすべての決定的なソースはfindutils documentatonです。


1
短く、簡潔で、find -L落とし穴と循環リンクに対処します。+1
Flimm 14年

いいね 最後のものはMacOSXでも動作しますが、@ rozcietrzewiaczの答えは動作しませんでした。
neu242

1
@ので、可能性がありneu242 -xtypePOSIXで指定し、あなたが見れば確かにされていないfind(1)MacOSの中で、それは持っている-typeもののません -xtype
プリフタン

7

-Lコマンドにフラグを追加すると、grepを削除できると思います。

$ find -L . -type l

http://www.commandlinefu.com/commands/view/8260/find-broken-symlinks

男から:

 -L      Cause the file information and file type (see stat(2)) returned 
         for each symbolic link to be those of the file referenced by the
         link, not the link itself. If the referenced file does not exist,
         the file information and type will be for the link itself.

19
最初はこれを支持しましたが、それがどれほど危険なのかを認識しました。それを使用する前に、私の答えを見てください
rozcietrzewiacz

6

リンクが壊れているか周期的であるかにかかわらず、別の動作が必要な場合は、findで%Yを使用することもできます。

$ touch a
$ ln -s a b  # link to existing target
$ ln -s c d  # link to non-existing target
$ ln -s e e  # link to itself
$ find . -type l -exec test ! -e {} \; -printf '%Y %p\n' \
   | while read type link; do
         case "$type" in
         N) echo "do something with broken link $link" ;;
         L) echo "do something with cyclic link $link" ;;
         esac
      done
do something with broken link ./d
do something with cyclic link ./e

この例は、この投稿(サイトが削除されました)からコピーされます。

参照


findコマンドがサポートしていない人のためのさらに別の略記はxtype、これから導き出すことができますfind . type l -printf "%Y %p\n" | grep -w '^N'。アンディは彼のスクリプトで同じ(基本的な)アイデアで私を打ち負かしたので、私はそれを別の答えとして書くことに消極的でした。:)
構文エラー

2

私はこれを私の場合に使用し、壊れたシンボリックリンクを探すディレクトリを知っているので、非常にうまく機能します:

find -L $path -maxdepth 1 -type l

私のフォルダにはへのリンクが含まれていますが、/usr/shareそれを横断しません。クロスデバイスリンクやchrootなどに有効なリンクは依然として落とし穴ですが、私のユースケースではそれで十分です。


2

OPのバージョンのバリエーションである、簡単な簡単な答え。簡単に入力したり覚えたりしたい場合があります:

find . | xargs file | grep -i "broken symbolic link"

1

find -L . -type l |xargs symlinks ファウンドファイルごとにリンクが存在するかどうかの情報を提供します。


1

これにより、現在のディレクトリにある壊れたシンボリックリンクの名前が出力されます。

for l in $(find . -type l); do cd $(dirname $l); if [ ! -e "$(readlink $(basename $l))" ]; then echo $l; fi; cd - > /dev/null; done

Bashで動作します。他のシェルについて知らない。

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