zsh在scp时不能使用通配符的原因和解决方案

问题

scp是经常使用的一个本地与远程服务器相互拷贝数据的命令,zsh是我最喜欢的shell,但是在zsh下使用scp来拷贝远程服务器的文件时,却出现这样的错误。

1
2
$ scp -r test-server:/etc/nginx/conf.d/* .
zsh: no matches found: test-server:/etc/nginx/conf.d/*

同样地命令,在bash下确实可以执行的,这个原因是什么呢?

由于zsh不会按照远程地址上的文件去扩展参数,当你使用test-server:/etc/nginx/conf.d/*,因为本地当前目录中,是不存在test-server:/etc/nginx/conf.d/*,所以匹配失败。默认情况下,bash 在匹配失败时就使用原来的内容,zsh 则报告一个no matches的错误。

解决方案

zsh中执行setopt nonomatch,告诉它不要报告no matches的错误,而是当匹配失败时直接使用原来的内容。

实际上,不管是 bash 还是 zsh,不管设置了什么选项,只要把test-server:/etc/nginx/conf.d/*加上引号,如"test-server:/etc/nginx/conf.d/*",就可解决问题。

当然根本的解决办法还是告诉zsh不要报告no matches错误。

执行下面的命令可以一劳永逸:

1
2
3
$ echo "setopt nonomatch" >> ~/.zshrc

$ echo "set -o nonomatch" >> ~/.zshrc