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


38

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

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

どうやってやるの?


まだシンボリックリンクを比較したい(そして同等であるが壊れていると識別した)か、またはこのdiffを実行するときにすべてのシンボリックリンクを無視してもよいですか?
ire_and_curses

比較して同等であると特定された場合、それらが壊れているかどうかは気にしません。rsyncが機能したことを確認しようとしています。
マーカスジュニウスブルータス

回答:


24

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

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

一部のファイルは、ディレクトリでも通常のファイルでもありません。それらは、シンボリックリンク、デバイス特殊ファイル、名前付きパイプ、ソケットなどの珍しいファイルです。現在、diff通常のファイルのようにシンボリックリンクを扱います。トップレベルで指定されている場合、通常のファイルのような他の特別なファイルを扱いますが、ディレクトリを比較するとき、それらの存在を単に報告します。これは、そのpatchようなファイルへの変更を表すことができないことを意味します。たとえば、シンボリックリンクが指すdiffファイルを変更すると、シンボリックリンクへの変更の代わりに、2つのファイル間の差分が出力されます。

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

必要なのがrsyncを検証する(そしておそらく欠落しているものを修正する)だけであれば、rsyncコマンドをもう一度実行するだけで済みます。そうしたくない場合は、ディレクトリのチェックサムで十分です。

でこれを本当に行いたい場合は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に存在していなくても気付かないでしょう。必要な場合は、すべてのシンボリックリンクを識別するために2番目の検索パスが必要になり、その後bでそれらの存在を明示的に確認します。
  • リストはaの内容から作成されるため、bの余分なファイルは識別されません。これはおそらくあなたのシナリオにとって問題ではありません。rsync

提案されたスクリプトは、ディレクトリ 'a'に存在するディレクトリに対して再帰的に機能しません(b / $ {f ## *}を使用して 'b'に対して作成されたパスは正しくありません)。
マーカスジュニウスブルータス14

@MarcusJuniusBrutus-はい、そうです。私は解決策は#を削除することだと思う、例えばfor f in a / *を見つける!-type l ;do echo $f b/${f#*/};done。でも今はこれをテストする時間がありません。それが機能するかどうか教えてください。
ire_and_curses 14

それはあるが、それはまだ多くの場合、ファイルパスを台無しに優れています。(#が削除された)スクリプトは、動作するために 'a'のすぐ上のディレクトリから呼び出す必要があるようです。
マーカスジュニウスブルータス14

GNU diff 3.3を使用すると、この答えは時代遅れになります(以下の投稿を参照)
Bernd Gloss

上記のスクリプトにはいくつかの問題があります。最初にすべてのファイル名を見つけて、それらを拡張されたコマンドラインに渡すためです。(1)それ以来、小さなファイルのコレクションでのみ動作します。(2)特殊文字を含むファイル名(スペースも含む)は処理されません。(3)$(xxx)バックティックの代わりに常に使用します。バックティックの対称性は、それらを読みにくくし、ネストを防ぎます。1および2については、stackoverflow.com
questions / 11366184 /を

19

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

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

同等または以下の場合、診断はサイレントになります。

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


シンボリックリンクが通常のファイルであるかのように、コンテンツの変更を表示するだけの場合は...:-/
lindes

6

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

diffGNUでdiffutils3.3は、--no-dereferenceあなたが彼らの目標ではなく、シンボリックリンクそのものを比較することができますオプションを選択します。それらが異なるかどうかを報告し、同意すれば静かで、壊れているかどうかは気にしません。

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


diff(GNU diffutils)3.2にも存在しないことを確認できます
オタク長老
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.