From da014e7c8e8c933662e0e8449bfbc2fd7b6d85fd Mon Sep 17 00:00:00 2001 From: Petr Houska Date: Tue, 4 Aug 2026 23:45:42 +0200 Subject: [PATCH] fix: normalize path separators for --full-path glob matches on Windows In glob mode the search regex is taken straight out of globset, which always emits `/` as the separator, both for literals (`\` in a pattern is parsed as `Token::Literal('/')` on Windows) and for the generated `[^/]`, `(?:/?|.*/)`, `/.*` constructs. globset's own matcher completes that contract by normalizing the candidate in `Candidate::new`, but fd uses the extracted regex directly, so with --full-path the pattern was `/`-separated while the candidate was a native Windows path and nothing ever matched. Normalize the candidate the same way globset does, but only when it can matter: --glob together with --full-path. --regex overrides --glob, so native-separator regexes keep seeing unmodified paths. See #2067. --- CHANGELOG.md | 1 + src/config.rs | 4 +++ src/main.rs | 2 ++ src/walk.rs | 16 ++++++++++- tests/tests.rs | 72 ++++++++++++++++++++++++++++++-------------------- 5 files changed, 65 insertions(+), 30 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 52b09d9f3..66564e4a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ - Fire the "search pattern contains a path separator" diagnostic for any pattern containing `/`, not just patterns that happen to name an existing directory. Preserves the legacy Windows behaviour that also flags native `\` separators when the pattern resolves to a real directory. See #1873. - Also fire the "search pattern contains a path separator" diagnostic for `--and` patterns, not only the primary positional pattern. `--and` patterns are matched against the file name just like the primary pattern, so a path separator in them silently returned zero results. See #1873. - Fix bug where passing "-" as a directory argument didn't actually search that directory, see #849 (@Sean-Kenneth-Doherty). +- Fix full-path glob patterns containing path separators on Windows, see #2067 (@petrroll). # 10.4.2 diff --git a/src/config.rs b/src/config.rs index a027812a4..3a98b6913 100644 --- a/src/config.rs +++ b/src/config.rs @@ -19,6 +19,10 @@ pub struct Config { /// Populated when `--full-path` is set; `None` means search by filename only. pub full_path_base: Option, + /// Whether to normalize native path separators before applying the search regex. + #[cfg(windows)] + pub normalize_path_separators: bool, + /// Whether to ignore hidden files and directories (or not). pub ignore_hidden: bool, diff --git a/src/main.rs b/src/main.rs index 609078b2b..2d8f3ddd2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -310,6 +310,8 @@ fn construct_config(mut opts: Opts, pattern_regexps: &[String]) -> Result