nushell: [bug] Glob and drive letter on Windows

Describe the bug

Glob doesn’t seem to work with drive letters on Windows.

How to reproduce

Try any of the following on Windows:

# Using backslash
glob C:\Users\User\AppData\Roaming\nushell\scripts\apps\*
# Using forward slash
glob C:/Users/User/AppData/Roaming/nushell/scripts/apps/*

let config_dir = ($nu.config-path | path dirname | path join 'scripts')

# Constructed from nu pipelines
glob $"($config_dir | path join 'apps')(char path_sep)*"
# Constructed from nu pipelines sanitized
$"($config_dir | path join 'apps')(char path_sep)*" | str replace -a '\\' '/' | path expand | glob $in
# Let's try simpler alts

glob "C:/*"
glob "C:\*"
glob "C:*"

All of the these return

Error:
  × error with glob pattern
  help: failed to parse glob expression

Expected behavior

To work as expected with absolute paths on windows, including drive letter.

Screenshots

No response

Configuration

key value
version 0.71.0
branch
commit_hash
build_os windows-x86_64
build_target x86_64-pc-windows-msvc
rust_version rustc 1.66.0-nightly (5c8bff74b 2022-10-21)
rust_channel nightly-x86_64-pc-windows-msvc
cargo_version cargo 1.66.0-nightly (3ff044334 2022-10-17)
pkg_version 0.71.0
build_time 2022-11-13 19:16:05 +01:00
build_rust_channel release
features database, dataframe, default, trash, which, zip
installed_plugins iselect

Additional context

No response

About this issue

  • Original URL
  • State: open
  • Created 2 years ago
  • Comments: 16 (5 by maintainers)

Most upvoted comments

Maintainer of wax here. I’m happy to participate, so I thought I’d comment with a few thoughts.

because [nu-glob] was breaking ls is some weird way.

Perhaps #5691?

I think it’s a good add for a composable pipeline.

I agree. While it is more verbose, I find the idea of a dedicated glob command more clear and consistent and I think wax could be a good fit for this (despite needing an additional mechanism for platform-specific path features). This may be an unpopular opinion, but I think something like glob -a *.txt | rm1 is preferable to rm -a *.txt. Going even further, commands (or the shell itself) need not support globbing at all. This would make globbing and path operations more obvious, keep globbing features contained to the glob command, and make documentation easier to find and read (it is more obvious where to look for globbing documentation and command documentation is less cluttered).

Regarding globs as an integrated shell feature, native paths with pattern extensions are the norm and users may be confused or otherwise react negatively to a departure from that, so it’s a bit less clear to me if wax is suitable as is. It would probably require the same mechanism for platform-specific path features in every command that supports globbing.

1Assuming rm can accept paths from standard input. An expansion or xargs equivalent could also do.

Hi again, folks! I’ve become aware of several Nushell issues that seem to relate to this one and there is a similar issue open against wax. I’d like to share some thoughts and crazy ideas and thought this may be a good place to do so: please let me know if there’s a better place though!

I’d really like to avoid introducing platform-specific features to glob expressions in wax. One tenant of that library is that glob expressions are portable and distinct from paths (and moreover are not “extended native paths”). wax glob expressions are the same everywhere. This doesn’t always work so well for the problems faced by a shell though.

This is a big departure from the way this is usually done, but I think the way that I’d prefer to address this problem is to provide a mechanism atop wax that allows native paths and patterns to be used together and yet remain distinct. I think @bobhy suggested something similar here, for example.

It needs more thought, but I’ve put together a quick proof of concept called treeish. That library provides a Treeish type, which joins native path prefixes and globs into a single expression. That repository includes an example CLI tool called findish that accepts a treeish and prints the paths of files with a matching path that it finds. A treeish looks something like the following and uses an optional :: separator in its explicit form:

  • **/*.txt
  • \\?\UNC\server\share::**/*.txt
  • C:\Users::**/AppData/**/*.savedgame
  • A:\novel.txt
  • \\?\GLOBALROOT\Device::HarddiskVolume<[0-9]:1,>

A Treeish can be one of three things:

  1. A native path. The parser prefers a native path interpretations in general.
  2. A glob pattern.
  3. A glob pattern in a particular tree (i.e., a native path prefix and a glob).

Rather than accepting or constructing paths (i.e., std::path::Path{Buf}), CLI programs can instead accept or construct a Treeish for any argument that should support patterns. Treeish may even help programs provide informative errors about arguments that should not accept patterns by detecting and rejecting them (at time of writing, via Treeish::new(...)?.path(), which return None if any patterns are parsed). Because treeish is just a library, it should be possible for applications that aren’t associated with Nushell to provide a similar interface too.

I just wanted to mention this idea in case anyone has thoughts or opinions about this kind of approach. It’s a bit unusual, but I really prefer distinguishing between paths (prefixes) and patterns. For better or worse, users on Unix may miss this altogether while users on Windows may see :: as a strange and unfair annoyance. I’m not sure. 😄 I may be off my rocker here.

To play with findish, clone the treeish repository and try cargo run -p findish -- '<treeish>' (note that the treeish expression is quoted to avoid escaping).

…replace every glob instances with (ls <globpatter>).name and ALL the samples I posted in the OP are now working.

Yes, that sounds right. I believe that commands like ls have direct support for globbing using a different in-tree library. That library always parses globs as native paths (via std::path), ignores any prefix and root components, and then extracts patterns from the remaining components. This approach has different tradeoffs than that of Wax and allows for native paths with pattern extensions (there’s no need to isolate platform-specific path features for the most part).

Our glob command uses the wax crate so this may be an upstream problem but I’m not positive.