Last active
May 16, 2018 16:45
-
-
Save mpacer/b3dc71db53d74de8e51de4a74119073f to your computer and use it in GitHub Desktop.
diff files quickly in subdirs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
import os | |
import glob | |
import itertools | |
import sys | |
import argparse | |
from subprocess import Popen, PIPE | |
def parseargs(): | |
parser = argparse.ArgumentParser(description='quickly diff files in subdirs') | |
parser.add_argument('filename', help="this is the file that you're looking for") | |
parser.add_argument('--exclude', dest="excluded", action="append", | |
help="pass in a string to exclude dirs with that string") | |
parser.add_argument('--only', dest="only", action="append", | |
help="pass in a string to include only dirs with that string") | |
return parser.parse_args() | |
def gen_dirs(fn, exclude_list=None, only_list=None): | |
if exclude_list is None: | |
exclude_list =[] | |
if only_list is None: | |
only_list =[] | |
return (d for d in glob.iglob('*') | |
if os.path.isdir(d) | |
and filter_dir_names(d, exclude_list, only_list) | |
and os.path.exists(os.path.join('.', d, fn))) | |
def filter_dir_names(d, exclude_list=None, only_list=None): | |
if exclude_list is None: | |
exclude_list =[] | |
if only_list is None: | |
only_list =[''] | |
only = any(s in d for s in only_list) if only_list else True | |
exclude = any(s in d for s in exclude_list) if exclude_list else True | |
return only and not exclude | |
def filename_writer(fn, excluded=None, only=None): | |
if excluded is None: | |
excluded = [] | |
if only is None: | |
only = [] | |
exclude_str = ('-'.join(['','excluding',*excluded])) if excluded else '' | |
include_str = ('-'.join(['','including', *only])) if only else '' | |
return f"diff-{fn}-report{include_str}{exclude_str}.txt" | |
def filter_list_to_str(f_list): | |
ret_str = "" | |
if len(f_list)==1: | |
ret_str+=f_list[0] | |
elif len(f_list)==2: | |
ret_str+=" and ".join(f_list) | |
elif len(f_list)>2: | |
ret_str+=f"{', '.join(f_list[:-1])}, and {f_list[-1]}" | |
return ret_str | |
def main(): | |
parser = parseargs() | |
fn = parser.filename | |
excluded = parser.excluded | |
only = parser.only | |
dir_gen = gen_dirs(fn, exclude_list=excluded, only_list=only) | |
output_file = filename_writer(fn, excluded, only) | |
if os.path.exists(output_file): | |
os.remove(output_file) | |
to_write = [] | |
no_diff_dict = {} | |
for d in itertools.combinations(dir_gen, 2): | |
f1, f2 = map(lambda x: os.path.join(x, fn), d) | |
d1, d2 = map(str, d) | |
header = f"{f1} compared to {f2} is different as follows:" | |
diff_cmd =['diff', f'{f1}', f'{f2}'] | |
p = Popen(diff_cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE) | |
output, err = p.communicate() | |
if output: | |
to_write.extend([header, f"{'-'*len(header)}"]) | |
to_write.append(f"{output.decode('utf-8')}\n") | |
else: | |
if d1 in no_diff_dict: | |
no_diff_dict[d1].append(d2) | |
elif d2 in no_diff_dict: | |
no_diff_dict[d2].append(d1) | |
else: | |
no_diff_dict[d1] = [d2] | |
no_diff_str = "\n".join([f" {', '.join(v)}, and {k}" | |
if len(v)>1 else f" {k} and {v[0]}" | |
for k, v in no_diff_dict.items()]) | |
no_diff_str= "There is no difference between:\n" + no_diff_str | |
with open(output_file, 'a') as f: | |
f.write(f"This is a report on the differences between the different files named {fn}.\n\n") | |
if to_write: | |
f.write(no_diff_str+"\n\n") | |
f.write("\n".join(to_write)) | |
else: | |
f.write(f"Are you sure that you meant to search for {fn}, " | |
f"{'including only ' +filter_list_to_str(only) + ' ' if only else ''}" | |
f"{'excluding ' +filter_list_to_str(excluded) if excluded else ''}?\n" | |
"There are no such files!") | |
if __name__=="__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment