web-dev-qa-db-ja.com

壊れたリンクに出力せずに、diff -rで2つのディレクトリを再帰的に比較します

使っています diff -r a bディレクトリabを再帰的に比較します。しかし、いくつかの壊れたリンク(abの両方のディレクトリに同じ壊れたリンクがあり、同じ存在しないターゲットを指している)があることはよくあります。

diffは、それらの場合のエラーメッセージを出力し、ゼロ以外の終了コードで終了しますが、無音のままにし、ディレクトリが私の本と同じであるため、0で終了します。

どうやってやるの?

44

diffのバージョン3.3以降の場合、 Pete Harlanの回答 で説明されているように、--no-dereferenceオプションを使用する必要があります。

残念ながら、古いバージョンのdiffシンボリックリンクを無視することはサポートしていません

一部のファイルは、ディレクトリでも通常のファイルでもありません。これらは、シンボリックリンク、デバイス特殊ファイル、名前付きパイプ、ソケットなどの異常なファイルです。現在、diffはシンボリックリンクを通常のファイルのように扱います。他の特殊ファイルが最上位で指定されている場合は、通常のファイルと同様に処理しますが、ディレクトリを比較するときに、その存在を報告するだけです。つまり、patchはそのようなファイルへの変更を表すことができません。たとえば、シンボリックリンクが指すファイルを変更すると、diffは、シンボリックリンクへの変更ではなく、2つのファイルの違いを出力します。

diffはオプションで特別なファイルへの変更を特別に報告し、patchはこれらの拡張機能を理解するために拡張する必要があります。

Rsyncを確認する(そしておそらく欠落しているものを修正する)ことだけが必要な場合は、rsyncコマンドをもう一度実行するだけで済みます。そうしたくない場合は、 check-summing the directory で十分です。

これをdiffで本当に実行したい場合は、findを使用してシンボリックリンクをスキップし、各ファイルに対して個別にdiffを実行できます。ディレクトリaおよびbを引数として渡します。

#!/bin/bash
# Skip files in $1 which are symlinks
for f in `find $1/* ! -type l`
do
    # Suppress details of differences
    diff -rq $f $2/${f##*/}
done

またはワンライナーとして:

for f in `find a/* ! -type l`;do diff -rq $f b/${f##*/};done

これにより、内容が異なるファイル、またはaにあるがbにないファイルが識別されます。

ご了承ください:

  • シンボリックリンクを完全にスキップしているので、bにシンボリックリンク名が存在しない場合、これは気付かないでしょう。それが必要な場合は、すべてのシンボリックリンクを識別し、bでそれらの存在を明示的に確認するための2番目の検索パスが必要になります。
  • b内の余分なファイルは識別されません。これは、リストがaの内容から作成されるためです。これはおそらくrsyncシナリオでは問題ではありません。
29
ire_and_curses

バージョン3.3以降GNU diffはシンボリックリンクの逆参照をサポートしていませんが、それらが指すパスを比較します。

GNU diffutils> = 3.3をインストールして、--no-dereferenceオプション;そのための短いオプションはありません。

等しいか次の場合、診断はサイレントになります:

シンボリックリンク/tmp/noderef/a/symlinkおよび/tmp/noderef/b/symlink異なる

21

diffの新しいバージョンを使用できます

GNU diff 3.3のdiffutilsには、--no-dereferenceオプションでは、ターゲットではなくシンボリックリンク自体を比較できます。それらが異なる場合は報告し、同意する場合は静かで、壊れているかどうかを気にしません。

オプションがいつ追加されたかはわかりません。 2.8.1には存在しません。

6
Pete Harlan