比較したい大きな木が2つあります。ツリーの一部のファイルは、最後に改行があるだけで異なり、他のファイルにはこの改行がありません。この事実は無視したい。私は次のようにdiff
を呼び出そうとしました:
diff --ignore-all-space -r <dir1> <dir2>
そして、これは機能しています。私の問題は、重要な場合がある他の違い(スペース関連)も無視することです。
要約すると、I just EOFの改行を無視したい。これはdiff
で可能ですか?
基本的に、後続のバイトを無視して、2つのファイルを比較する必要があります。これを行うための「diff」オプションはありません-しかし、それを行う方法はいくつかあります(たとえば、16進diffも思い浮かびます)。
'diff'を使用するには、基本的に、ファイルの最後で改行が欠落しているファイルを変更してから、比較する必要があります。変更されたファイルを使用して一時ディレクトリを作成するか、スクリプトを少し実行してメモリ内で実行できます。 (どちらが好ましいかは、設定、ファイルサイズ、ファイル数によって異なります...)
たとえば、次の例では、ファイルの内容を変更し(sed -i
を使用してその場で変更します。これはstdoutに出力されるだけです)、欠落している場合は改行を追加します(または、既に改行がある場合はファイルを変更しません)。 :
sed -e '$a\' file1.txt
そして、単に 'diff'構文を確認します(trueを返すことは同じであることを意味し、falseは異なることを意味します):
$ diff a/file1.txt b/file1.txt \
&& echo '** are same' || echo '** are different'
2c2
< eof
---
> eof
\ No newline at end of file
** are different
空白のみが異なることを確認します。
$ diff --ignore-all-space a/file1.txt b/file1.txt \
&& echo '** are same' || echo '** are different'
** are same
Bashでは、 'sed'を使用して、ファイルの内容を 'diff'に渡すときに操作できます(元のファイルは変更されません)。
$ diff <(sed -e '$a\' a/file1.txt) <(sed -e '$a\' b/file1.txt) \
&& echo '** are same' || echo '** are different'
** are same
あとは、diff -r
をエミュレートしてディレクトリを再帰的に比較するだけです。ディレクトリa
とb
を比較する場合、a
内のすべてのファイル(例:a/dir1/dir2/file.txt
)の場合、b
(例: 、b/dir1/dir2/file.txt
)と比較してください:
$ for f in $( find a -type f )
> do
> diff <(sed -e '$a\' $f) <(sed -e '$a\' b/${f#*/})
> done
もう少し詳細なバージョン:
$ for f in $( find a -type f )
> do
> f1=$f
> f2=b/${f#*/}
> echo "compare: $f1 $f2"
> diff <(sed -e '$a\' $f1) <(sed -e '$a\' $f2) \
> && echo '** are same' || echo '** are different'
> done && echo '** all are same' || echo '** all are different'
compare: a/file1.txt b/file1.txt
** are same
compare: a/file2.txt b/file2.txt
** are same
** all are same
各ファイルに改行を追加し、diffの空白行を無視することで問題を解決しました(オプション-B
)。この解決策はユースケースに適さない場合がありますが、他の人を助けるかもしれません:
echo >> $FILE1
echo >> $FILE2
diff -B $FILE1 FILE2
答えは簡単です。
欠落している改行に関するメッセージは、diff
の出力ストリームではなく、エラーストリームにあります。だからそれをニルヴァーナに曲げれば、あなたは永遠に終わります
diff -rqEeB fileA fileB 2> /dev/null
別のアプローチも考えてみてください。これは大きなファイルでも機能します(元のファイルをコピーまたは変更しません)。それでも、再帰的なディレクトリトラバーサルをエミュレートする必要があります(そのための方法はいくつかあります)が、この例では「sed」を使用せず、cmp
、たとえば、
$ cmp a/file1.txt b/file1.txt && echo '** are same' || echo '** are different'
cmp: EOF on b/file1.txt
** are different
$ du -b a/file1.txt b/file1.txt
13 a/file1.txt
12 b/file1.txt
$ cmp -n 12 a/file1.txt b/file1.txt && echo '** are same' || echo '** are different'
** are same
それでもディレクトリ内のすべてのファイルをループし、2つのファイルa/file.txtとb/file.txtの場合は、大きい方のファイルサイズを計算し、1つを減算してから、これを使用してバイナリ差分(cmp
)を実行しますバイト数(bashでも):
(( bytes = $(du -b a/file.txt b/file.txt | sort -nr | head -1 | cut -f1) - 1 ))
cmp -n $bytes a/file.txt b/file.txt
ファイルのループは、sed
とdiff
を使用した他の回答と同じです。
diff
の出力をgrep
コマンドにパイプして、表示したくないメッセージをドロップします。