tools: add cli for hardlinks
This commit is contained in:
parent
1f8a64601b
commit
bb49652985
@ -11,6 +11,9 @@ class Colors:
|
|||||||
WHITE = "\033[37m"
|
WHITE = "\033[37m"
|
||||||
|
|
||||||
class BaseCli:
|
class BaseCli:
|
||||||
|
def __init__(self, debug=False):
|
||||||
|
self.debug_enabled=debug
|
||||||
|
|
||||||
def info(self, message):
|
def info(self, message):
|
||||||
print(f'[{Colors.GREEN}INFO{Colors.RESET}] {message}')
|
print(f'[{Colors.GREEN}INFO{Colors.RESET}] {message}')
|
||||||
|
|
||||||
@ -19,4 +22,9 @@ class BaseCli:
|
|||||||
|
|
||||||
def error(self, message, exit_code=1):
|
def error(self, message, exit_code=1):
|
||||||
print(f'[{Colors.RED}ERROR{Colors.RESET}] {message}')
|
print(f'[{Colors.RED}ERROR{Colors.RESET}] {message}')
|
||||||
sys.exit(exit_code)
|
sys.exit(exit_code)
|
||||||
|
|
||||||
|
def debug(self, message):
|
||||||
|
if not self.debug_enabled:
|
||||||
|
return
|
||||||
|
print(f'[{Colors.BLUE}DEBUG{Colors.RESET}] {message}')
|
||||||
118
services/tools/cli/create_hardlinks.py
Executable file
118
services/tools/cli/create_hardlinks.py
Executable file
@ -0,0 +1,118 @@
|
|||||||
|
#!/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()
|
||||||
Loading…
x
Reference in New Issue
Block a user