diff --git a/src/dippy/cli/find.py b/src/dippy/cli/find.py index 5f3f139..1493968 100644 --- a/src/dippy/cli/find.py +++ b/src/dippy/cli/find.py @@ -14,6 +14,11 @@ COMMANDS = ["find"] +# Actions that write find's output to a file (truncating it) — same effect as a +# `> file` redirect, which Dippy already guards. The `f` prefix means "file" +# (vs. -print/-printf/-ls which write to stdout and are safe). +FILE_WRITE_ACTIONS = frozenset({"-fprint", "-fprint0", "-fprintf", "-fls"}) + # Context for flags that aren't self-explanatory FLAG_CONTEXT = { "-ok": "execute with prompt", @@ -36,6 +41,10 @@ def classify(ctx: HandlerContext) -> Classification: if token == "-delete": return Classification("ask", description=f"{base} -delete") + # -fprint/-fprintf/-fls write output to a file (truncating it) + if token in FILE_WRITE_ACTIONS: + return Classification("ask", description=f"{base} {token}") + # -exec/-execdir - extract inner command and delegate if token in ("-exec", "-execdir"): inner_tokens = [] diff --git a/tests/cli/test_find.py b/tests/cli/test_find.py index a4dd874..edaad3f 100644 --- a/tests/cli/test_find.py +++ b/tests/cli/test_find.py @@ -138,10 +138,6 @@ ("find . -printf '%f\\n'", True), ("find . -printf '%p %s\\n'", True), ("find . -ls", True), - ("find . -fls /tmp/output.txt", True), - ("find . -fprint /tmp/output.txt", True), - ("find . -fprint0 /tmp/output.txt", True), - ("find . -fprintf /tmp/output.txt '%p\\n'", True), # # --- Boolean operators (safe) --- # @@ -251,6 +247,14 @@ ("find /tmp -name '*.cache' -delete", False), ("find . -mtime +30 -delete", False), # + # --- -fprint/-fprintf/-fls (write output to a file, truncating it) --- + # + ("find . -fprint /tmp/output.txt", False), + ("find . -fprint0 /tmp/output.txt", False), + ("find . -fprintf /tmp/output.txt '%p\\n'", False), + ("find . -fls /tmp/output.txt", False), + ("find . -name '*.py' -fprint /etc/hosts", False), + # # --- Combinations with safe exec --- # ("find . -name '*.py' -print -exec cat {} \\;", True),