Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

default settings cause scp/rsync to fail with remote globbing #2945

Closed
psifertex opened this issue Jul 11, 2014 · 8 comments
Closed

default settings cause scp/rsync to fail with remote globbing #2945

psifertex opened this issue Jul 11, 2014 · 8 comments

Comments

@psifertex
Copy link

scp user@hostname:file*.tgz .
Fails with: "zsh: no matches found: user@hostname:file*.tgz

Bash does the convenient thing: fails to expand, then simply passes along the argument to the application so it can handle it.

This happens with rsync as well. Here's a workaround I found online:

__remote_commands=(scp rsync)
autoload -U url-quote-magic
zle -N self-insert url-quote-magic
zstyle -e :urlglobber url-other-schema '[[ $__remote_commands[(i)$words[1]] -le ${#__remote_commands} ]] && reply=("*") || reply=(http https ftp)'

But that's somewhat sub-optimal. Among other problems, I've noticed it has trouble when you paste text.

I understand I can escape the *, but I'd rather not since it's muscle-memory to be undone and is the sort of thing that will turn someone off when they're trying to migrate from bash to zsh.

@mcornella
Copy link
Member

You can alias those to noglob COMMAND, that way the globbing symbols are not interpreted. I have git aliased to it so HEAD^ and similar don't try globbing.
I don't know if there's any other workaround.

@psifertex
Copy link
Author

Except it seems like there might very well be times I'd /want/ to glob for git? Or maybe git itself will handle it even if the shell doesn't?

@ncanceill
Copy link
Contributor

This is a Zsh issue, not OMZ. Consequently, please close this using the button at the bottom of the page — you can keep posting messages afterwards, and we will kindly try to help you, but at least it will be one less issue open with OMZ.


Back to your problem — let me assume that you will be closing this promptly anyway.

I strongly advise you against what you want to do. If a globbing/regex pattern should be expanded out of the shell (like with your scp example, where the pattern should be expanded at the remote computer), then it SHOULD be quoted/escaped — note that instead of escaping the asterisk, you can (and probably should) quote the entire path, like so:

$ scp user@hostname:"file*".tgz .

If you really really want to take the bad easy way, you can simply unsetopt no_match. This will get you the Bash behavior:

$ unsetopt no_match
$ echo i_dont_exist*
i_dont_exist*
$ setopt no_match
$ echo i_dont_exist*
zsh: no matches found: i_dont_exist*

But again, you SHOULD not do that. To quote my source:

If you happened to have a file which matched that pattern in your current directory when running that command any of those shells would expand the pattern to match that file before running [the command], this is unlikely to give the results that you are expecting.

@psifertex
Copy link
Author

Thanks for the reply. Closing the issue now, though I could use a bit more explanation as to why unsetting no_match is a bad idea? At least for scp style commands not expanding is exactly the behaviour I would expect.

@psifertex
Copy link
Author

Reading over that page more carefully I guess my response is the same as the one commenter's: failing to execute the command isn't necessarily more friendly. And that's what I was led to believe oh-my-zsh was about -- an easy, clean introduction to zsh's powerful features. In that regard, I'd expect it to ease me into the transition a bit more, and why I'd argue that maybe this is a default option that /should/ be considered for inclusion.

There's potential problems on both sides, so I'd default to the principle of least surprise -- and for most folks, that's what they're used to on existing shells.

@ncanceill
Copy link
Contributor

"that's what I was led to believe oh-my-zsh was about -- an easy, clean introduction to zsh's powerful features"

Not sure where you read that. The ReadMe clearly defines the project as:

[a] framework for managing your ZSH configuration. It comes bundled with a ton of helpful functions, helpers, plugins, themes [...]

OMZ is about making you shell easier to use, not easing the transition to Zsh. Also, I personally like my shell to be strict: it seems we disagree on the principle of least surprise.

About switching: let's face it, if you go from Bash to Zsh, you are in for a bunch of surprises anyway — most of them will be good, but some (like globbing errors) may feel bittersweet.


As to why using no_match can be harmful, building on your example:

$ ls /folder
file_a file_b

$ ssh user@host ls /folder
file_c file_d

$ unsetopt no_match
# If you do not use no_match,
# you are used to quoting your globbers
$ scp user@host:"/folder/file*" .
# Copies file_c and file_d to current dir,
# so it works

$ setopt no_match
# If you use no_match, then you are
# not used to quoting your globbers
$ scp user@host:/folder/file* .
# Tries to copy file_a and file_b from
# remote host, so it fails

You can imagine much worse scenarios.

@psifertex
Copy link
Author

First, thanks for taking the time to engage on this topic. My impression of omz is based on recommendations I've heard, but at this point I don't remember exactly where so it's either my mis-remembering or who knows what. Appreciate the reminder of the summary.

That said, while there may be some instances where no_match is dangerous, the example you showed above isn't one, mostly because it's wrong.

It's not dangerous because " user@host:/folder/file* " won't expand in zsh because @ and : are valid in file names. Given that, I wouldn't expect scp or rsync to ever have a problem (unless you happened to have files matching username@hostname:path that /also/ matched).

Just to verify, I went and ran that experiment and it did indeed behave as expected (slightly edited 'cause sudo):

$ mkdir /folder
$ touch /folder/file_a
$ touch /folder/file_b
$ ssh remote@host "mkdir /folder;touch /folder/file_c; touch /folder/file_d"
$ unsetopt no_match
$ scp remote@host:/folder/file* .
file_c                                        100%    0     0.0KB/s   00:00
file_d                                        100%    0     0.0KB/s   00:00

Anyway, I concede that there might indeed be /some/ instances where it's potentially dangerous, but I've been using /bin/sh and variants for quite some time now without running into one, so I'm comfortable taking the risk. On this note, I think we'll just agree to disagree, but thanks again for pointing out the option in the first place.

@mcornella
Copy link
Member

FWIW, on my noglobbed git, using tab to expand a globbing character such as * or ^ still works. I don't know why it does, I guess that's an acceptable use case (if the user typed TAB to expand a glob on a noglobbed command, the probable intention is to use globbing).


Updated with an example:

For instance, on a git repo:

$ git commit -m ^poo[ENTER]

creates a commit with the message being ^poo, while:

$ git add ^poo[TAB]

expands to all files except ones named poo.
Note that pressing ENTER instead will throw the error:

fatal: pathspec '^poo' did not match any files

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants