web-dev-qa-db-ja.com

diffがファイルの終わりで改行をチェックしないようにする

比較したい大きな木が2つあります。ツリーの一部のファイルは、最後に改行があるだけで異なり、他のファイルにはこの改行がありません。この事実は無視したい。私は次のようにdiffを呼び出そうとしました:

diff --ignore-all-space -r <dir1> <dir2>

そして、これは機能しています。私の問題は、重要な場合がある他の違い(スペース関連)も無視することです。

要約すると、I just EOFの改行を無視したい。これはdiffで可能ですか?

22
dangonfast

基本的に、後続のバイトを無視して、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をエミュレートしてディレクトリを再帰的に比較するだけです。ディレクトリabを比較する場合、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
17
michael

各ファイルに改行を追加し、diffの空白行を無視することで問題を解決しました(オプション-B)。この解決策はユースケースに適さない場合がありますが、他の人を助けるかもしれません:

echo >> $FILE1 
echo >> $FILE2
diff -B $FILE1 FILE2 
2
Jakob

答えは簡単です。
欠落している改行に関するメッセージは、diffの出力ストリームではなく、エラーストリームにあります。だからそれをニルヴァーナに曲げれば、あなたは永遠に終わります

diff -rqEeB fileA fileB 2> /dev/null
0
yunzen

別のアプローチも考えてみてください。これは大きなファイルでも機能します(元のファイルをコピーまたは変更しません)。それでも、再帰的なディレクトリトラバーサルをエミュレートする必要があります(そのための方法はいくつかあります)が、この例では「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

ファイルのループは、seddiffを使用した他の回答と同じです。

0
michael

diffの出力をgrepコマンドにパイプして、表示したくないメッセージをドロップします。

0
David Schwartz