3

From https://linux.die.net/man/1/zshmisc :

noglob
Filename generation (globbing) is not performed on any of the words.

zsh example:

$ ls /*
  <lots of output>
$ noglob ls /*
ls: cannot access '/*': No such file or directory
$ ls "/*"
ls: cannot access '/*': No such file or directory

In fish, this works with quotes:

$ ls "/*"
ls: cannot access '/*': No such file or directory

Is it possible in fish to do the same thing without requiring quotes?

6
  • 1
    This is a good example of a "feature" that should never have been implemented and why I stopped using zsh long ago. Commented Jan 5, 2021 at 20:49
  • Absolutely agree. There are some features I often think I miss from zsh, but when I see the Fish team's reasoning behind why they did it differently, it almost always makes more sense. Commented Jan 5, 2021 at 20:57
  • 1
    @snapshoe What's your ultimate goal with the noglob behavior? I'm guessing it's something more subtle than the command-line usage you demonstrated itself. Commented Jan 5, 2021 at 20:59
  • 1
    I frequently do 'find' commands like find /path -name "*.ext", and I shortened that with a zsh noglob alias to simply do findf /path/*.ext which finds all files in all subdirs under path, including those in /path. I've used '**' wildcards in fish. I'm perfectly open to the answer being "No", and I'm not a great fan of noglob either. But it is nice to have a function or alias with the noglob in it when I don't want to have to put quotes around args all the time. I'm just getting familiar with with fish recently, and this is one small thing I came across.
    – snapshoe
    Commented Jan 5, 2021 at 23:03
  • Makes sense - The alias case is greatly simplified by having noglob precede the command. Do you use additional find arguments with findf or always as above? Can you provide your entire alias here? I think I might have a fish alternative. Commented Jan 6, 2021 at 23:27

1 Answer 1

4

Original answer: Regarding noglob behavior itself, I'm fairly certain the answer is "No", per this Github issue.

Edit/Update: But given the use-case you describe in the comments, there may be another way to avoid typing the quotes, albeit nowhere near as straightforward as noglob.

For the sake of keeping this as simple as possible, I deviated slightly from your example in the comments. According to that example, you use noglob in zsh to create an alias so that:

findf /path/*.ext maps to find /path -name "*.ext"

I went with using a space to separate the path and the name into two distinct parameters:

findf /path *.ext maps to find /path -name "*.ext"

Well, sort of - At least that's what you would type. The workaround in this case is to get fish to add the surrounding quotes for you automatically when you type an argument to findf with a * wildcard.

To do that, set up three functions (two of them are just one-liners), all in ~/.config/fish/functions:

findf.fish:

function findf --description 'alias findf=find {path} -name {name}'
    find $argv[1..-2] -name $argv[-1]
end

Pretty straightforward - Just passes the last argument to findf as the -name argument to find.

Then the real workhorse. findf_binding.fish:

function findf_binding 
    commandline -i '*'
    set -l tokens (commandline -bo)
    if test (count $tokens) -gt 0
    and [ $tokens[1] = "findf" ]
        set -l currentToken (commandline -t)
        if not contains "\"" (string split "" $currentToken)
            set -l replaceToken "\""$currentToken"\""
            set -l cursorPos (commandline --cursor)
            commandline -t $replaceToken
            commandline --cursor (math $cursorPos+1)
        end
    end
end

This basically boils down to "If * is pressed, and the line starts with findf, and argument with the * isn't quoted already, then quote it and move the cursor after the *."

Finally, bind the * to the findf_binding in fish_user_key_bindings.fish:

function fish_user_key_bindings
    bind '*' findf_binding
end

Full disclosure - This is my first keybinding script in fish. It's a fish feature that I've been wanting to learn/try out for a while now, and I saw this as a good opportunity. As a result, though, there are undoubtedly some corner cases that I missed, and style or syntax improvements that could be made.

For instance, as a known limitation, if you ever want to use wildcards to match multiple paths (e.g. findf path* *.yaml) this binding will erroneously add quotes to the path component as well.

But hopefully this gets you close to what you are looking for, or at least puts you on the right track to tweak it or write your own.

1
  • I'm comfortable with the original "No" answer. Binding to '*' is an interesting idea I hadn't considered, and seems to address replacing noglob. I agree there seems like there would be corner cases, and I do appreciate the huge effort. I will experiment with binding to '*' and see where it leads me.
    – snapshoe
    Commented Jan 7, 2021 at 17:35

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .