2

I am a relatively new zsh user, and love it 99% of the time. When I try to copy a bunch of files, eg:

[I] ➜ ls *17*
core.txt.17   info.17       vmcore.17.zst

but when I scp *17* xxx:xxx/xxx, I get:

[I] ➜ scp *17* freefall.freebsd.org:
*17*: No such file or directory

ler in /var/crash  at borg
[I] ➜

Why?

If I run type scp, I get:

scp is an alias for noglob scp
scp is /usr/bin/scp
  • What's the ler in /var/crash  at borg at the end of the scp output about? Is scp really scp or is it an alias or shell function? – Kusalananda Jul 15 '19 at 15:58
  • @Kusalananda, I think that's the first line of their prompt. – ilkkachu Jul 15 '19 at 16:40
  • that is the first line of my prompt. scp is not an alias that I've added (it might be something for the completer but I'm sure (using prezsto). – Larry Rosenman Jul 16 '19 at 2:03
  • what happens if you execute /usr/bin/scp directly? – sendmoreinfo Jul 20 '19 at 12:42
  • @sendmoreinfo that works. I'm still curious what the hades is going on when it's found on the PATH. – Larry Rosenman Jul 21 '19 at 15:34
3

As you've discovered, zsh has a way to disable wildcard expansion on certain commands. If you put noglob before a command, zsh doesn't do wildcard expansion on the words of the command. Since typing noglob is often as much effort as quoting wildcard characters in arguments, the most common use is to automatically cause certain commands to be “noglobbed” by making the command name an alias to the same command name with the noglob prefix. For example, after

alias scp='noglob scp'

you won't get any wildcard expansion on the scp command line, but other than that the scp command will run normally.

You can bypass the alias with

\scp *17* freefall.freebsd.org: 

or

=scp *17* freefall.freebsd.org: 

\scp bypasses the alias and looks for a function, builtin or external command by that name. =scp only looks for an external command.

Preventing wildcard expansion for arguments of scp lets you write scp remote:*17* without quotes, but it comes with the major downside of not letting you write scp *17* remote:. It's possible to take this further and cause arguments of scp to have wildcards expanded only if they don't look like remote file names. Here's a function that analyzes the arguments of scp and only expands wildcards in arguments that don't look like options or remote file names.

function glob_non_remote {
  local a x
  a=($1); shift
  for x; do
    # Do wildcard expansion manually, but only for arguments that don't look
    # like options or remote file names.
    case $x in
      (*:*|-*|) a+=("$x");;
      *) a+=($~x);;
    esac
  done
  "${(@)a}"
}
alias scp='noglob glob_non_remote scp'
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.