我是一个相对较新的 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'