dotfiles/interactive_copy.py

57 lines
1.8 KiB
Python
Executable File

#!/usr/bin/env python3
"""Interactively and recursively copy files, prompting user when file
differs, showing him diffs.
"""
from filecmp import cmpfiles
from difflib import unified_diff
from os.path import expanduser, join, isdir, exists, dirname
from os import listdir, makedirs
from shutil import copy2 as copy
from itertools import chain
def maybe_copy_file(src, dest):
if not exists(dest):
if input("Copy {} [y,n]? ".format(src)).lower()[0] == 'y':
makedirs(dirname(dest), exist_ok=True)
copy(src, dest)
return
with open(src) as a, open(dest) as b:
diff = unified_diff(list(b), list(a))
print(''.join(list(diff)))
if input("Copy {} [y,n]? ".format(src)).lower()[0] == 'y':
copy(src, dest)
def maybe_copy_dir(src, dest, common):
matches, missmatches, errors = cmpfiles(src, dest, common, shallow=False)
for match in sorted(matches):
print(join(dest, match), '')
for missmatch in sorted(chain(missmatches, errors)):
if isdir(join(src, missmatch)):
maybe_copy_dir(join(src, missmatch), join(dest, missmatch),
listdir(join(src, missmatch)))
else:
maybe_copy_file(join(src, missmatch), join(dest, missmatch))
def parse_args():
import argparse
parser = argparse.ArgumentParser(description='Interactively copy files.')
parser.add_argument('src')
parser.add_argument('dest')
parser.add_argument('--exclude', help='Exclude those files', nargs='*',
default=[])
return parser.parse_args()
def main(src, dest, exclude):
maybe_copy_dir(expanduser(src), expanduser(dest),
set(listdir(src)) - set(exclude))
if __name__ == '__main__':
main(**vars(parse_args()))