#!/usr/bin/env python3 import os import sys import argparse from argparse import ArgumentParser from args_utils import dir_arg_type from base import BaseCli CLI_DESCRIPTION=''' Create hard links of files from source to destination. ''' class CreateHardlinksCli(BaseCli): def configure_args(self, parser: ArgumentParser): parser.add_argument( '-s', '--source', required=True, help="Source folder" ) parser.add_argument( '-d', '--destination', required=True, help="Destination folder", ) parser.add_argument( '-v', '--verbose', help="Increase verbosity", default=False, action='store_true' ) def process_args(self, parser: ArgumentParser): args = parser.parse_args() return args def __init__(self): parser = ArgumentParser(description=CLI_DESCRIPTION) self.configure_args(parser) self.args = self.process_args(parser) super().__init__(debug=self.args.verbose) def __create_file_ln__(self, src, dest): if os.path.exists(dest): self.debug(f"Hard link already exists: {dest} -> {src}") else: os.link(src, dest) self.debug(f"Created hard link: {dest} -> {src}") def create_hardlinks(self, src, dest): if not os.path.exists(dest): os.makedirs(dest) self.info(f"Created destination directory: {dest}") if os.path.isfile(src): self.info('Source is a file. Hardlinking and quitting.') dest_file = os.path.join(dest, os.path.basename(src)) self.__create_file_ln__(src, dest_file) return for dirpath, dirnames, filenames in os.walk(src): relative_path = os.path.relpath(dirpath, src) dest_dir = os.path.join(dest, relative_path) if not os.path.exists(dest_dir): os.makedirs(dest_dir) self.debug(f"Created directory: {dest_dir}") for filename in filenames: src_file = os.path.join(dirpath, filename) dest_file = os.path.join(dest_dir, filename) self.__create_file_ln__(src_file, dest_file) def print_tree(self, directory, level=0): """Print the directory tree.""" if level == 0: self.info('Hardlinked Result:') indent = " " * (level * 4) print(f"{indent}{os.path.basename(directory)}/") for item in os.listdir(directory): path = os.path.join(directory, item) if os.path.isdir(path): self.print_tree(path, level + 1) else: print(f"{indent} {item}") def count_files_in_directory(self, directory): if not os.path.isdir(directory): self.warning(f"Can't count files in {directory}, because it is a file") return 0 total_files = 0 for dirpath, dirnames, filenames in os.walk(directory): total_files += len(filenames) return total_files def start(self): self.create_hardlinks( self.args.source, self.args.destination ) self.print_tree(self.args.destination) src_files = self.count_files_in_directory(self.args.source) dest_files = self.count_files_in_directory(self.args.destination) self.info(f'Files in source direcotry: {src_files}') self.info(f'Files in destination directory: {dest_files}') def main(): cli = CreateHardlinksCli() cli.start() if __name__ == "__main__": main()