Add a dry-run mode to a Python cleanup command

A cleanup command should make its candidate set visible before it removes anything. Default to a preview, restrict work to a directory chosen by the operator and require a separate flag for execution.
The same candidate policy feeds preview or explicit execution; this example never recurses.
Keep the first version deliberately narrow
The following command checks immediate files in a supplied fixture directory. It removes only regular files ending in ".tmp"; it does not recurse or follow symbolic links.
import argparse
from pathlib import Path
def main():
parser = argparse.ArgumentParser()
parser.add_argument("directory", type=Path)
parser.add_argument("--execute", action="store_true")
args = parser.parse_args()
root = args.directory.resolve(strict=True)
if not root.is_dir():
parser.error("directory must be a directory")
candidates = sorted(
path for path in root.iterdir()
if path.suffix == ".tmp"
and not path.is_symlink()
and path.is_file()
)
for path in candidates:
print(("REMOVE" if args.execute else "PREVIEW"), path)
if args.execute:
path.unlink()
if __name__ == "__main__":
main()
Run it against a temporary directory containing "keep.txt" and "discard.tmp". The first invocation should print the temporary file and leave both files present. Add "--execute" for the second invocation and confirm only the candidate disappears. A third run should find nothing to remove.
The resolved absolute directory makes the operator's target visible. In a service, enforce a configured allowed root as well; a command accepting arbitrary operator-selected paths is a different authorization model. Reject a root that falls outside the application's intended working area before enumerating candidates.
Decide what a preview promises
Two invocations do not form one transaction. A file may change after the preview. If the execution command rescans the directory, it may select a file created after the operator reviewed the first list.
For a stronger review workflow, save a manifest containing each candidate's resolved path, size and modification metadata, then revalidate it during execution. Metadata comparisons still have race conditions. A hostile shared directory requires stronger operating-system-level file handling than this small example provides.
Handle permission errors as failures, with a nonzero exit status and a useful path message. Do not catch every exception and print "done": that makes a partially completed cleanup indistinguishable from success.
The operational automation in Postzyo offers related context. The relevant interfaces are documented in argparse and pathlib.