48 lines
1.5 KiB
Python
48 lines
1.5 KiB
Python
from argparse import ArgumentParser
|
|
from itertools import zip_longest
|
|
from pathlib import Path
|
|
|
|
CHUNK_SIZE = 16
|
|
|
|
|
|
def hl(b: str):
|
|
return f"\033[31;47;1m{b}\033[0m"
|
|
|
|
|
|
if __name__ == "__main__":
|
|
parser = ArgumentParser()
|
|
parser.add_argument("file1", type=Path, help="First file.")
|
|
parser.add_argument("file2", type=Path, help="Second file.")
|
|
args = parser.parse_args()
|
|
|
|
# Read files
|
|
with open(args.file1, "rb") as fd1, open(args.file2, "rb") as fd2:
|
|
file1 = fd1.read()
|
|
file2 = fd2.read()
|
|
|
|
# Find differences
|
|
diff = [b1 == b2 for b1, b2 in zip_longest(file1, file2, fillvalue=-1)]
|
|
|
|
n1 = len(file1)
|
|
n2 = len(file2)
|
|
values1 = [f"{b:02X}" for b in file1]
|
|
values2 = [f"{b:02X}" for b in file2]
|
|
|
|
# Highlight different values
|
|
values1 = [b if diff[i] else hl(b) for i, b in enumerate(values1)]
|
|
values2 = [b if diff[i] else hl(b) for i, b in enumerate(values2)]
|
|
|
|
# Pad to same length
|
|
values1 = values1 + [" "] * (max(n1, n2) - n1)
|
|
values2 = values2 + [" "] * (max(n1, n2) - n2)
|
|
|
|
# Print bytes in chunks
|
|
print()
|
|
print(args.file1.name, " " * ((3 * CHUNK_SIZE - 1) + 2 - len(args.file1.name)), args.file2.name)
|
|
print("-" * (3 * CHUNK_SIZE - 1), " ", "-" * (3 * CHUNK_SIZE - 1))
|
|
for chunk in [slice(i, i + CHUNK_SIZE) for i in range(0, max(n1, n2), CHUNK_SIZE)]:
|
|
print(" ".join(values1[chunk]), " ", " ".join(values2[chunk]))
|
|
|
|
print()
|
|
print(f"Files differ at {diff.count(False)} places.")
|