From f29373b2b81f3a72970f05115bc523e03ff3902e Mon Sep 17 00:00:00 2001 From: Patrick szymkowiak Date: Fri, 13 Mar 2026 11:39:49 +0100 Subject: [PATCH] fix: skip rewriting find/fd in pipes to preserve xargs compatibility (#439) rtk find outputs a grouped format incompatible with pipe consumers like xargs, grep, wc, sort. Skip rewrite when find/fd is followed by a pipe, preserving native one-per-line output. Signed-off-by: Patrick szymkowiak --- src/discover/registry.rs | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/src/discover/registry.rs b/src/discover/registry.rs index 03e606a5..70a7836f 100644 --- a/src/discover/registry.rs +++ b/src/discover/registry.rs @@ -355,8 +355,18 @@ fn rewrite_compound(cmd: &str, excluded: &[String]) -> Option { } else { // `|` pipe — rewrite first segment only, pass through the rest unchanged let seg = cmd[seg_start..i].trim(); - let rewritten = - rewrite_segment(seg, excluded).unwrap_or_else(|| seg.to_string()); + // Skip rewriting `find`/`fd` in pipes — rtk find outputs a grouped + // format that is incompatible with pipe consumers like xargs, grep, + // wc, sort, etc. which expect one path per line (#439). + let is_pipe_incompatible = seg.starts_with("find ") + || seg == "find" + || seg.starts_with("fd ") + || seg == "fd"; + let rewritten = if is_pipe_incompatible { + seg.to_string() + } else { + rewrite_segment(seg, excluded).unwrap_or_else(|| seg.to_string()) + }; if rewritten != seg { any_changed = true; } @@ -1071,6 +1081,30 @@ mod tests { ); } + #[test] + fn test_rewrite_find_pipe_skipped() { + // find in a pipe should NOT be rewritten — rtk find output format + // is incompatible with pipe consumers like xargs (#439) + assert_eq!( + rewrite_command("find . -name '*.rs' | xargs grep 'fn run'", &[]), + None + ); + } + + #[test] + fn test_rewrite_find_pipe_xargs_wc() { + assert_eq!(rewrite_command("find src -type f | wc -l", &[]), None); + } + + #[test] + fn test_rewrite_find_no_pipe_still_rewritten() { + // find WITHOUT a pipe should still be rewritten + assert_eq!( + rewrite_command("find . -name '*.rs'", &[]), + Some("rtk find . -name '*.rs'".into()) + ); + } + #[test] fn test_rewrite_heredoc_returns_none() { assert_eq!(rewrite_command("cat <<'EOF'\nfoo\nEOF", &[]), None);