Created
March 22, 2023 16:45
-
-
Save cn-ml/88ddf34c07af2d8b9aa2be236ce554ef to your computer and use it in GitHub Desktop.
Python script for executing a command for every file (similar to linux "find -exec" command)
This file contains 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
from argparse import REMAINDER, ArgumentParser, BooleanOptionalAction | |
from pathlib import Path | |
from subprocess import run | |
from typing import Sequence | |
class ProgramException(Exception): | |
pass | |
def parse_args(): | |
parser = ArgumentParser(description="Execute a command for all files in a directory.") | |
parser.add_argument("-r", "--recursive", type=bool, default=False, action=BooleanOptionalAction, help="Whether to recursively select files.") | |
parser.add_argument("-d", "--dry", type=bool, default=False, action=BooleanOptionalAction, help="Whether to dry run the commands.") | |
parser.add_argument("-p", "--placeholder", type=str, default="FILE", help="Placeholder for the filename in the command.") | |
parser.add_argument("-m", "--match", type=str, default="*", help="Pattern to match the base filename against.") | |
parser.add_argument("directory", type=Path, help="Directory to select files from.") | |
parser.add_argument("command", nargs=REMAINDER, metavar="CMD", help="Command to execute.") | |
return parser.parse_args() | |
def run_shell_command(file_cmd: Sequence[str], dry: bool=False): | |
if dry: | |
print("Command:", file_cmd) | |
return | |
process = run(file_cmd, shell=True) | |
if process.returncode != 0: | |
raise ProgramException(f"Shell command '{' '.join(file_cmd)}' failed!") | |
def program(directory: Path, command: Sequence[str], placeholder: str, recursive: bool=False, dry: bool=False, pattern: str="*"): | |
if not placeholder in command: | |
raise ProgramException(f"Placeholder '{placeholder}' must be used in the command!") | |
globber = directory.rglob if recursive else directory.glob | |
entries = globber(pattern) | |
files = (file for file in entries if file.is_file()) | |
for file in files: | |
file_cmd = [str(file) if arg == placeholder else arg for arg in command] | |
run_shell_command(file_cmd, dry) | |
def main(): | |
args = parse_args() | |
try: | |
program(args.directory, args.command, args. placeholder, args.recursive, args.dry, args.match) | |
except ProgramException as e: | |
print(f"Program failed: {e}") | |
exit(1) | |
except Exception as e: | |
print(f"Unhandled exception: {e}") | |
exit(2) | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment