ssh 上的 zmv (zsh) 在 shell 和腳本之間的行為不同
我非常感謝
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
and-W
選項。該-W
選項是唯一不會出錯的選項,因此例如我可以這樣做:ssh me@myserver "cd /Users/me/mypath; autoload zmv; zmv -n -W 'xxx_*_*_*.*' '*-*-*.*'"
它有效。但是,如果我省略
*
了替換組中的一個,zmv 會說:“錯誤:每個模式中的萬用字元數量必須匹配”,當我試圖省略部分原始文件名時,這並沒有多大幫助。我應該怎麼做?
這裡的問題是引用 - 並不特定於 zsh 或 zmv
在你的命令下
ssh me@myserver "cd /Users/me/mypath; autoload zmv; zmv '(xxx_)(*)' 'yyy_$2'"
“弱”外部雙引號不會阻止本地外殼程序
$2
將其擴展為(可能是空$2
的)位置參數 - 所以遠端外殼程序看到的是cd /Users/me/mypath; autoload zmv; zmv '(xxx_)(*)' 'yyy_'
如果匹配兩個文件,則zmv
(xxx_)(*)
嘗試將它們都重命名為yyy_
both map to yyy_
替換中具有萬用字元模式的版本(由
-W
開關啟用)不會遇到同樣的問題,因為萬用字元(shell glob)即使在雙引號中也不會擴展。解決此問題的最簡單方法是添加另一層引用,以便
$2
不受干擾地傳遞到遠端 shell:ssh me@myserver "cd /Users/me/mypath && autoload zmv && zmv '(xxx_)(*)' 'yyy_\$2'"
這裡也使用
&&
而不是,;
因為如果失敗,您不想zmv
執行cd
,否則您最終會重命名me
’s 主目錄中的文件myserver
。有關引用和 SSH 問題的更一般性討論,包括使用此處文件的替代解決方法,請參閱相關問題