我真的很感激帮助zmv
通过 ssh 在脚本中按预期工作。
我正在尝试更改我可以完全控制的远程服务器上的文件名。本地和远程计算机都运行 macOS 10.14.6,并使用 zsh 作为默认 shell。
如果我打开 zsh 终端窗口,通过 ssh 连接然后输入zmv '(xxx_)(*)' 'yyy_$2'
,它会按预期工作。但是如果我将 zmv 放入 ssh 中,我假设我必须将其打包到脚本中:
ssh me@myserver "cd /Users/me/mypath; autoload zmv; zmv '(xxx_)(*)' 'yyy_$2'"
它失败了,因为 zmv 对每个文件对说:“都映射到 yyy_”。换句话说,要么它无法识别匹配组,要么反向引用不起作用。
我只是了解 zsh 和 ssh 是两种不同类型的 shell,并且具有不同的环境,所以例如我发现我需要,autoload zmv
即使它位于远程计算机上的 .zshrc 中。我尝试过添加noglob zmv
(再次在 .zshrc 中设置),并且我尝试过转义任何数量的东西。
我还尝试了zmv 的-w
和-W
选项。该-W
选项是唯一不会出错的选项,所以例如我可以这样做:
ssh me@myserver "cd /Users/me/mypath; autoload zmv; zmv -n -W 'xxx_*_*_*.*' '*-*-*.*'"
它有效。但是,如果我省略替换组中的其中一个*
,zmv 会说:“错误:每个模式中的通配符数量必须匹配”,当我试图省略原始文件名的部分内容时,这没有多大帮助。
我应该怎么做?
答案1
这里的问题是引用 - 并且不特定于 zsh 或 zmv
在你的指挥下
ssh me@myserver "cd /Users/me/mypath; autoload zmv; zmv '(xxx_)(*)' 'yyy_$2'"
“弱”外部双引号不会阻止本地 shell$2
扩展为(可能为空)位置参数$2
- 所以远程 shell 看到的是
cd /Users/me/mypath; autoload zmv; zmv '(xxx_)(*)' 'yyy_'
如果(xxx_)(*)
匹配两个文件,则 zmv 尝试将它们重命名为,yyy_
并产生错误both map to yyy_
替换中具有通配符模式的版本(由-W
开关启用)不会遇到同样的问题,因为即使在双引号中,通配符(shell 全局变量)也不会扩展。
解决该问题的最简单方法是添加另一层引用,以便$2
不受干扰地传递到远程 shell:
ssh me@myserver "cd /Users/me/mypath && autoload zmv && zmv '(xxx_)(*)' 'yyy_\$2'"
这里也使用&&
代替,;
因为如果失败你不想zmv
运行cd
,否则你最终会重命名me
主目录中的文件myserver
。
有关引用和 SSH 问题的更一般性讨论,包括使用此处文档的替代解决方法,请参阅相关问题