#!/usr/bin/python3 from glob import glob from os import remove as os_remove from os.path import isdir as path_isdir, isfile as path_isfile, abspath, \ basename from pathlib import Path from re import sub as re_sub from shutil import rmtree DRY_RUN = False remove_comments = lambda s: re_sub(r"(? str: with open(path, "r", encoding="utf-8-sig") as gitignore_file: res = gitignore_file.read().splitlines() return res def delete(file_path: str) -> None: is_dir = path_isdir(file_path) is_file = path_isfile(file_path) if not (is_dir or is_file): return display_file_path = abspath(file_path) if DRY_RUN: if is_dir: print("Removing directory", display_file_path) elif is_file: print("Removing file", display_file_path) if DRY_RUN: return if is_dir: rmtree(file_path, ignore_errors=True) elif is_file: os_remove(file_path) def extend_wildcards(patterns: list) -> list: res = [] for pattern in patterns: processed_line = remove_comments(pattern).strip() if processed_line.startswith("!"): exception_pattern = processed_line[1:] exceptions = glob(exception_pattern, recursive=True) res = [path for path in res if path not in exceptions] else: res.extend(glob(processed_line, recursive=True)) return res def clean_gitignored_files(base_path: str = ".") -> None: for gitignore_path in list(Path(base_path).rglob("*.gitignore")): for file_path in extend_wildcards(read_gitignore(gitignore_path)): delete(file_path) if __name__ == "__main__": from sys import argv if "-h" in argv or "--help" in argv: print("Usage:", basename(argv[0]), "[options]") print() print("[ ]: Optional arguments") print() print("Options:") print(" -h, --help: Display this help text") print(" -d, --dry-run: Only list files") else: if (argc := len(argv)) == 2 and argv[1] in ["-d", "--dry-run"]: DRY_RUN = True clean_gitignored_files()