diff --git a/hardlink_creator.py b/hardlink_creator.py new file mode 100644 index 0000000..85085a3 --- /dev/null +++ b/hardlink_creator.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python3 + +import os +import json +import argparse + + +def create_hardlinks(json_file, source_dir, target_dir, dry_run: bool = False): + """ + Reads the JSON file and creates hardlinks based on the mapping of source and target files. + + Args: + json_file (str): Path to the JSON file containing the mapping. + source_dir (str): Base path of the source directory. + target_dir (str): Base path of the target directory. + dry_run (bool): If True, no changes will be made; actions will be printed instead. + """ + try: + with open(json_file, 'r') as f: + file_mappings = json.load(f) + except Exception as e: + print(f"Failed to read JSON file {json_file}: {e}") + return + + for source_file, target_file in file_mappings: + source_path = os.path.join(source_dir, source_file) + target_path = os.path.join(target_dir, target_file) + + # Ensure the source file exists + if not os.path.exists(source_path): + print(f"Source file does not exist: {source_path}. Skipping...") + continue + + # Ensure the target directory exists + target_dir_path = os.path.dirname(target_path) + if not os.path.exists(target_dir_path): + if dry_run: + print(f"[DRY-RUN] Would create directory: {target_dir_path}") + else: + print(f"Creating directory: {target_dir_path}") + os.makedirs(target_dir_path, exist_ok=True) + + # Create the hard link if the target does not already exist + if not os.path.exists(target_path): + if dry_run: + print(f"[DRY-RUN] Would create hard link: {source_path} -> {target_path}") + else: + print(f"Creating hard link: {source_path} -> {target_path}") + try: + os.link(source_path, target_path) + except OSError as e: + print(f"Failed to create hard link for {target_path}: {e}") + else: + print(f"Target file already exists, skipping: {target_path}") + + +def main(): + parser = argparse.ArgumentParser(description="Create hardlinks based on JSON output from the first script.") + parser.add_argument('json_file', help="Path to the JSON file containing source-target mappings.") + parser.add_argument('source_dir', help="Path to the source directory.") + parser.add_argument('target_dir', help="Path to the target directory.") + parser.add_argument( + '--dry-run', '-n', + action='store_true', + help="Perform a dry run; only print actions without making changes." + ) + args = parser.parse_args() + + create_hardlinks(args.json_file, args.source_dir, args.target_dir, args.dry_run) + + +if __name__ == "__main__": + main() diff --git a/hardlink_mapper.py b/hardlink_mapper.py new file mode 100644 index 0000000..cdc2944 --- /dev/null +++ b/hardlink_mapper.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python3 + +import os +import sys +import json +import argparse + + +# Function to get hard links between source and target directories +def get_hard_links(source_dir, target_dir): + # Dictionary to store hard links + source_links = {} + target_links = {} + + # Walk through the source directory to collect hard links + for dirpath, _, filenames in os.walk(source_dir): + for filename in filenames: + filepath = os.path.join(dirpath, filename) + try: + inode = os.stat(filepath).st_ino + if inode not in source_links: + source_links[inode] = [] + source_links[inode].append(filepath) + except FileNotFoundError: + continue + + # Walk through the target directory to collect hard links + for dirpath, _, filenames in os.walk(target_dir): + for filename in filenames: + filepath = os.path.join(dirpath, filename) + try: + inode = os.stat(filepath).st_ino + if inode not in target_links: + target_links[inode] = [] + target_links[inode].append(filepath) + except FileNotFoundError: + continue + + # Generate the list of tuples (relative_src, relative_dst) + hard_links = [] + for inode, target_files in target_links.items(): + if inode in source_links: + for target_file in target_files: + relative_target = os.path.relpath(target_file, target_dir) + for source_file in source_links[inode]: + relative_source = os.path.relpath(source_file, source_dir) + hard_links.append([relative_source, relative_target]) + + return hard_links + + +def main(): + # Argument parser for CLI arguments + parser = argparse.ArgumentParser(description="Collect hard links between source and target directories.") + parser.add_argument('source_dir', help="Path to the source directory") + parser.add_argument('target_dir', help="Path to the target directory") + + args = parser.parse_args() + + hard_links = get_hard_links(args.source_dir, args.target_dir) + print(json.dumps(hard_links, indent=2)) + + +if __name__ == "__main__": + main()