Skip to content

Provide a string that does not expand globs #9558

@haitemura

Description

@haitemura

Related problem

Motivating example:
Recently I downloaded a video with yt-dlp. This tool puts youtube's video id into the file name in brackets, like so: video_title [video_id].webm. I wanted to mv the file and used tab completion to get its name, but the returned string did not match the video title. This was because it didn't escape the glob characters [ and ]. Hence, I had to fire up zsh to move the file.

There is currently no simple way to define a string which does not expand glob characters when working with file paths.
In #6014, it was implemented that glob expansion does not happen in " and ' strings, but only when an external command is executed.
I think this is confusing, see here:

touch a *
ls '*' # shows both files
^ls '*' # shows only one file

I believe that having behaviour differ for externals and built-ins like that is confusing and counterintuitive.

As far as I know, the only way right now to circumvent glob expansion when you're not doing external commands is by creating a character class—in which there can be no nested globs—so that *, and friends are not parsed as glob characters, like so:

touch "hello [world] *"
rm `hello [[]world[]] [*]` # this works

This is very hard to read and I don't event know if it is the intentional way to deal with this kind of problem.

Describe the solution you'd like

  1. Have single-quoted (') strings not expand globs, regardless of where they're used.
  2. Make glob characters escapable in double-quoted (") strings.
  3. Remove the different treatment of glob expansion for external commands (as introduced in Conditionally disable expansion for external command #6014).

Describe alternatives you've considered

An alternative could be to do it like bash and have globs only be expanded in bare strings, but this would require cumbersome notation when mixed with spaces:

ls *.rs # expand
ls "*.rs" # don't expand
ls ("the folder/" + *.rs) # expand, mixed with space -> need concatenation

Though, maybe this could in fact be an alternative if string concatenation didn't require the + operator and parentheses. (i.e. if adjacent strings were concatenated like in bash.)

Additional context and details

There's a discussion in #4631 about this. The requirements @jntrnr mentioned there would be satisfied by a non-expanding single-quoted string:

  • A glob that expands automatically: "*.rs"
  • A glob looking thing that doesn't expand automatically: '*.rs'
  • A path with a space and a glob that expands automatically: "my files/*.rs"
  • A path with a space and a glob that doesn't expand automatically 'my files/*.rs'
    With Windows path syntax you could write the third bullet as "my files\\*.rs".

Also, this is a list of some issues this would fix:

Lastly, I noticed that glob behaviour is different in ls to how it is with mv, cp and rm. Here's an example:

touch a b c aa bb cc
ls ? # does not work, "directory not found"
mkdir somedir
mv ? somedir # moves the three shorter files as expected

Another example:

touch "[]" # "escaped" file name is "[[][]]"
ls "[[][]]" # does not work, "Pattern, file or folder not found"
mv "[[][]]" nice_name # works

When doing the above, ls returns this error: Pattern, file or folder not found.
I believe this difference in behaviour may possibly (partially?) be caused by recent pull request #9416, as doing the same with an asterisk works fine:

touch "*"
ls "[*]" # works fine, expected output

Maybe this last part about ls belongs in its own issue, but it is somewhat related.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A:file-systemRelated to commands and core nushell behavior around the file systemA:globBehavior around file-system globbing with regular commands or `glob`. See also A:quoting/expansionA:quoting-expansionIssues related to string quoting, interpolation, and expansion of variable or glob patternscategory:enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions