SSHによるzmv(zsh)は、シェルとスクリプトの間で異なる動作をします。

SSHによるzmv(zsh)は、シェルとスクリプトの間で異なる動作をします。

zmvSSHを介してスクリプトで期待どおりに機能するのを手伝ってくれてありがとう。

私は完全に制御できるリモートサーバーのファイル名を変更しようとしています。ローカルシステムとリモートシステムはどちらもmacOS 10.14.6を実行しており、zshをデフォルトのシェルとして使用しています。

zshターミナルウィンドウを開き、sshを介して接続し、と入力すると期待zmv '(xxx_)(*)' 'yyy_$2'どおりに機能します。しかし、zmvをsshに入れると、スクリプトでパッケージ化する必要があるとします。

ssh me@myserver "cd /Users/me/mypath; autoload zmv; zmv '(xxx_)(*)' 'yyy_$2'"

zmvはすべてのファイルペアに対して「yyy_にマップされます」と言うので失敗します。つまり、一致するグループを認識していないか、逆参照が機能しないということです。

autoload zmv私はzshとsshが2つの異なるタイプのシェルであり、異なる環境を持っていることを理解しています。たとえば、リモートシステムの.zshrcにあってもそうする必要があることがわかりました。追加(再び.zshrcに設定)を試み、noglob zmvいくつかのことをエスケープしてみました。

私もzmv-w-Wオプションを試しました。この-Wオプションは間違っていない唯一のオプションなので、たとえば、次のようにすることができます。

ssh me@myserver "cd /Users/me/mypath; autoload zmv; zmv -n -W 'xxx_*_*_*.*' '*-*-*.*'"

効果があるただし、代替グループの1つを省略すると、*zmvは「エラー:各パターンのワイルドカード数が一致する必要があります」と言います。これは、元のファイル名の一部を省略しようとするとあまり役に立ちません。

どうすればいいですか?

答え1

ここでの問題は参照にあり、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_'

2つのファイルが一致すると、(xxx_)(*)zmvはファイル名を次のように変更しようとするとyyy_エラーが発生します。both map to yyy_

代替バージョン(スイッチで有効)では、ワイルドカードモードのバージョンは-W同じ問題を受けません。ワイルドカード(シェルグローバル変数)は二重引用符内でも拡張されないためです。

$2問題を解決する最も簡単な方法は、干渉なしにリモートシェルに渡す別の参照層を追加することです。

ssh me@myserver "cd /Users/me/mypath && autoload zmv && zmv '(xxx_)(*)' 'yyy_\$2'"

また、失敗した場合は実行したくないので、ここで&&代わりに使用してください。それ以外の場合は、ホームディレクトリのファイル名が変更されます。;zmvcdmemyserver

ここに記載されている代替解決策を含む、参照とSSHの問題に関するより一般的な議論については、関連する問題を参照してください。

関連情報