为什么 zsh 不喜欢 *17* 这样的文件 glob?

为什么 zsh 不喜欢 *17* 这样的文件 glob?

我是一个相对较新的 zsh 用户,99% 的时间都喜欢它。当我尝试复制一堆文件时,例如:

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

但是当我scp *17* xxx:xxx/xxx,我得到:

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

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

为什么?

如果我运行type scp,我会得到:

scp is an alias for noglob scp
scp is /usr/bin/scp

答案1

正如您所发现的,zsh 有一种方法可以禁用某些命令的通配符扩展。如果你把noglob在命令之前,zsh 不会对命令的单词进行通配符扩展。由于输入noglob通常与在参数中引用通配符一样费力,因此最常见的用途是通过将命令名称设为具有前缀的相同命令名称的别名来自动导致某些命令“不被匹配” noglob。例如,在

alias scp='noglob scp'

您不会在scp命令行上获得任何通配符扩展,但除此之外该scp命令将正常运行。

您可以绕过别名

\scp *17* freefall.freebsd.org: 

或者

=scp *17* freefall.freebsd.org: 

\scp绕过别名并通过该名称查找函数、内置或外部命令。=scp只寻找外部命令。

scp防止 参数的通配符扩展允许您在不使用引号的情况下编写scp remote:*17*,但它的主要缺点是不允许您编写scp *17* remote:。可以更进一步,scp仅当参数看起来不像远程文件名时才扩展通配符。这是一个分析参数的函数,scp并且仅扩展看起来不像选项或远程文件名的参数中的通配符。

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'

相关内容