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


21

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

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

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

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

回答:


17

基本的に、2つのファイルを比較し、条件付きで後続バイトを無視する必要があります。これを行うための「diff」オプションはありませんが、それを行う方法はいくつかあります(たとえば、hex 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

sed -e '$a\'正確に何をするのか説明していただけますか?THX
törzsmókus

run sed-eファイルの終わりに一致する次の()スクリプト/式()が与えられ、$"追加"アクション(a \)を実行しますが、実際にはテキスト( `\`の後には何も)を指定しません。ファイルの最後にEOF / newlineを追加します(欠落している場合のみ)。
マイケル

THX。私はまだ見てa\ いません。
törzsmókus

1

各ファイルに改行を追加し、diff(オプション-B)の空白行を無視することで問題を解決しました。このソリューションは、ユースケースに適さない場合がありますが、他の人には役立つ場合があります。

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

0

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


良くない。--ignore-all-spaceを追加しない場合、diff -rは結果!= 0で存在します。明確にするために、diffはEOFで改行を無視し、EOFでのみ無視するようにします。そして、この基準に一致する結果を報告してほしい。つまり、ツリー内のファイルがEOFの改行でのみ異なる場合、それは差と見なしてはならないため、diffは0を返す必要があります
。– dangonfast

0

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

それでもディレクトリ内のすべてのファイルをループし、a / file.txtとb / file.txtの2つのファイルについて、大きいファイルサイズを計算し、1を減算してから、cmpこのバイト数を使用してバイナリdiff()を実行します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

答えは簡単です。
行方不明の改行に関するメッセージは、出力ストリームではdiffなくエラーストリームにあります。だからnに曲げると、あなたは長続きします

diff -rqEeB fileA fileB 2> /dev/null

diffは、違いを見つけてその値を確認したい場合、値!= 0を返します。/ dev / nullにリダイレクトしても、diffはその違いを忘れません。したがって、返される値は!= 0であり、これは望ましくありません。最後の改行
dangonfast、

-1

diff commnadにはフラグがあり--strip-trailing-crます:それはまさにあなたが要求したことをします


-1。これを試しましたか?EOFの直前にある/r/nもの/nと同様に扱われ、extraとは関係ありません/n
カミルマシオロウスキ

私はこれを試しましたが、異なるdos / unix改行を使用してファイルを差分するために使用しました...それは正しいのではないですか?
ダーマン

問題は、EOF(ファイルの終わり)での改行のみを無視することです。
カミルマチオロウスキ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.