Linuxでのファイル差分の確認方法

Linuxでのファイル差分の確認方法の実務上の結論は「review可能なtext差分はdiff -u、byte単位の一致はcmp、離れたcopyの照合はSHA-256を使い分けます。差分確認とpatch適用を同じ段階にしません。」です。比較前に「同一」をtext意味、byte列、metadataのどれで定義するか決めます。diffやcmpのstatus 1は差ありであり、read failureを示す2以上と同じ再試行queueへ入れません。

目次

diffの終了statusを三段階で読む

textの内容差はdiff -u、byte単位で同一かだけを見るならcmp、directory treeの比較はdiff -rが入口です。ただしowner、mode、ACL、xattr、timestampなどmetadataは通常の内容diffだけでは完全に比較できません。改行、encoding、生成順、localeによる差もあり、何を同一とするかを先に定義しないと、差を隠すoptionが誤判定につながります。

diff -uは前後context付きでreviewしやすく、–labelで一時pathを意味ある名前へ置換できます。-wや-Bは空白や空行を無視しますが、source codeや設定では意味のある変更も消し得ます。cmp –silentはbyte同一性のstatus判定向けです。directory比較では除外pattern、symbolic link、別filesystem、special fileの扱いを明記します。

text差・byte差・metadata差の合格基準を定める

  • textかbinaryかを確認する
  • 意味差とbyte差のどちらを判定するか決める
  • 改行、encoding、localeの扱いを固定する
  • 比較中にfileが変化しないsnapshotを用意する

比較中に片方が更新されるなら結果を採用しません。両側のsizeとhashを前後で記録し、CRLF、encoding、生成順を正規化する必要がある場合は、比較optionではなく承認済み前処理として仕様化します。

diff・cmp・SHA-256を目的別に走らせる

unified diffを表示

diff -u -- ./before.conf ./after.conf

終了code 0は同一、1は差あり、2はtroubleとして分けます。

同一かを静かに判定

cmp -s -- ./before.bin ./after.bin
rc=$?
case "$rc" in
  0) printf '%s\n' 'identical' ;;
  1) printf '%s\n' 'different' ;;
  *) printf 'cmp_error=%s\n' "$rc" >&2; exit "$rc" ;;
esac

cmpの0は同一、1はbyte差、2以上はreadやoption等のerrorとして分岐し、error statusを保持します。

最初のbyte差を表示

cmp -- ./before.bin ./after.bin

binaryの差位置を確認し、内容全体はterminalへ出しません。

SHA-256を比較

sha256sum -- ./before.bin ./after.bin

同じdigest algorithm、同じbyte列であることを確認します。

空白差を調査用に表示

diff -u --ignore-trailing-space -- ./before.txt ./after.txt

無視optionは調査補助であり、正式なbyte同一判定には使いません。

内容差・metadata差・構造差を分ける

diffはline-orientedなtext差分、cmpはbyte比較です。diffの終了code 1は通常の差ありでerrorではありません。whitespace無視やcase無視は差を隠すため、正式判定とreview補助を分けます。hash一致は強いbyte同一性確認ですが、信頼できるmanifestや署名の代わりではありません。

GNU diffは差なしで0、差ありで1、read errorやoption errorなど問題発生で2以上を返します。差ありの1をcommand失敗として再試行しても内容は一致しません。逆にpipelineや表示toolで最終statusが0になり、diffのerrorが隠れることがあります。stdoutの差分、stderr、終了statusを別々に保存し、空出力でもstatusを確認します。

binary判定、encoding不一致、CRLF/LF、権限不足、途中更新、broken linkを区別します。大きな生成物をtext diffするとmemoryやI/O負荷が増え、比較中にsourceが更新されると一貫しない結果になります。『Binary files differ』だけでは差の位置や安全性は分からず、hash、size、format固有validatorへ切り替えます。

差あり1と読取error2以上を混同しない

  • diff終了code 1を実行errorとする
  • 空白無視結果を完全同一と呼ぶ
  • binaryをtext diffで大量表示する
  • 変更中file同士を一回だけ比較する
  • digestのalgorithmやmanifest sourceを確認しない

diff/cmpの0は同一、1は差あり、2以上はoptionやread等の問題として記録します。1を再実行して一致を待たず、2以上ならstderrと権限を直して同じsnapshotを再試験します。

snapshot同士を比較しpatch適用を切り離す

比較中は原本を編集せず、必要ならread-only snapshotを使います。diff出力にsecretが含まれるため共有先を制限します。patchを適用する場合は別承認、backup、dry-run相当、rollback、post-apply hashを設けます。

差分表示は読み取りでも、そこからpatch、rsync、上書きへ直結させると影響が変わります。秘密情報を含む設定diffをticketや公開logへ貼らず、masking後も意味が残る最小範囲だけ共有します。merge前はbackupまたはversion管理commitを確保し、差分が空になったことだけでserviceの正常性を判断しません。

再現可能な差分検証

同一、1行差、末尾newline差、CRLF/LF、encoding差、binary差、read errorをsample化します。diff/cmp/hashの結果と終了codeを期待表へ記録し、原本hashが不変か確認します。

同一file、一文字変更、空白だけ、改行だけ、binary一byte変更、read不可、処理中更新をfixtureにします。diff -u、cmp、必要なmetadata取得のstdout・stderr・statusを期待表へ照合し、差あり1とerrorを別の合格条件にします。patch適用を伴う検証はcloneまたはcopyで行い、原本へ自動反映しません。

CIで0・1・2以上を用途別にmappingする

CIでは終了status 0を一致、1を期待された差、2以上をtool errorとして明示し、用途に応じて1をpassかfailへmappingします。生成順が不定ならsourceを正規化する専用処理を定義し、diff側で広く無視しません。比較前後のhashとsizeを採取し、sourceが変化したrunを無効として再取得します。

差の種類からsemantic comparatorを選ぶ

code reviewや設定比較にはunified diff、完全なbyte一致にはhashまたはcmp、directory同期の設計にはmetadataとlinkも扱えるtoolを選びます。JSONやXMLなど順序や空白の意味が構造依存ならparse後のsemantic comparisonを使います。差を見つける目的と、どちらを正本にする判断を分離して記録します。

diffの終了値は、0が差分なし、1が差分あり、2以上が読取りやoptionなどのerrorです。差分ありを実行失敗へまとめず、CIでは期待する状態に応じて1を判定へ組み込みます。binary判定や文字code、改行codeの違いで表示が変わるため、fileとlocaleを記録し、比較対象のhashとsizeも併せて残すと再検証できます。

合格は同一・一byte差・read不可fixtureでcmpの0・1・2以上を保ったままCI判定へ写せることです。比較前後のhashが変わったrunは破棄し、snapshotを作り直します。

公式情報・参考資料

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次