Created
July 16, 2025 18:09
-
-
Save d3flex/1d364c56ab42f5080c0da5befe381948 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
| import logging | |
| import argparse | |
| import pathlib | |
| import os | |
| import shutil | |
| import time | |
| logger = logging.getLogger(__name__) | |
| logger.setLevel(logging.INFO) | |
| def init_log(logname): | |
| console_logger = logging.StreamHandler() | |
| console_logger.setLevel(logging.INFO) | |
| file_logger = logging.FileHandler(logname) | |
| file_logger.setLevel(logging.INFO) | |
| formatter = logging.Formatter( | |
| '%(asctime)s - %(name)s - %(levelname)s - %(message)s') | |
| file_logger.setFormatter(formatter) | |
| console_logger.setFormatter(formatter) | |
| logger.addHandler(console_logger) | |
| logger.addHandler(file_logger) | |
| return logger | |
| def add_or_update(src, dest): | |
| pass | |
| def remove(src, dest): | |
| pass | |
| def sync(src, dest, interval): | |
| """ | |
| Recursively copies a directory and its contents, preserving all metadata. | |
| :param src: The path to the source directory to copy. | |
| :param dest: The path to the destination directory. | |
| :interval: duration before run again. | |
| """ | |
| logger.info(f"* Syncing {str(src)} directory to {str(dest)}.") | |
| os.makedirs(dest, exist_ok=True) | |
| shutil.copystat(src, dest) | |
| import pdb | |
| #pdb.set_trace() | |
| src_context = {p for p in pathlib.Path(src).rglob('*')} | |
| dst_context = {p for p in pathlib.Path(dest).rglob('*')} | |
| diff_set = dst_context - src_context | |
| # delete first | |
| if len(diff_set) > 0: | |
| for path in diff_set: | |
| if path.is_dir(): | |
| path.rmdir() | |
| if path.is_file(): | |
| path.unlink() | |
| else: | |
| logger.info("No deleted files.") | |
| for item in src.iterdir(): | |
| filename = item.name | |
| dst_fullpath = dest.joinpath(filename) | |
| #print(dst_fullpath) | |
| if item.is_dir(): | |
| sync(item, dst_fullpath, interval) | |
| else: | |
| shutil.copy2(item, dst_fullpath) | |
| logger.info(f"{str(item)} -> {str(dest)} sync completed.") | |
| time.sleep(interval) | |
| def main(): | |
| parser = argparse.ArgumentParser( | |
| prog='veeamsync', | |
| description='synchronizes two folders') | |
| parser.add_argument('source') | |
| parser.add_argument('replica') | |
| parser.add_argument('interval') | |
| parser.add_argument('sync_times') | |
| parser.add_argument('log_filename') | |
| args = parser.parse_args() | |
| logger = init_log(args.log_filename) | |
| from_dir = pathlib.Path(args.source) | |
| to_dir = pathlib.Path(args.replica) | |
| interval = int(args.interval) | |
| if (not from_dir.exists() or not from_dir.is_dir()): | |
| logger.error(f"source dir {args.source} not found") | |
| else: | |
| sync_times_left = int(args.sync_times) | |
| while (sync_times_left > 0): | |
| logger.info(f"Sync {sync_times_left} starts!") | |
| sync_times_left-=1 | |
| try: | |
| sync(from_dir, to_dir, interval) | |
| except Exception as e: | |
| logger.error(e) | |
| if __name__ == '__main__': | |
| main() | |
| # assuptions: | |
| # - all the params are mandatory and will be given |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment