web-dev-qa-db-ja.com

リモートSSH接続でrsyncを使用する場合のリモートパス内のスペースのエスケープ

SSHを使用してrsyncをリモートサーバーに接続する場合、リモートパスのスペースなどをどのようにエスケープしますか?単純なバックスラッシュはローカルbashプロンプトのスペースをエスケープしますが、リモートマシンではスペースはパスの区切りとして読み取られ、そのパスの終わりを示します。

つまり、rsync -avz /path/to/source/some\ dir/ [email protected]:/path/to/dest/some\ dir/を実行すると、リモートサーバーがそれを/path/to/dest/some/として読み取っていて、宛先がリモートで見つからないためです。実際の宛先は単に「ではなく、いくつかのディレクトリ」であるためです。いくつか"。

同じコマンドを試してバックスラッシュとスペースをエスケープしてローカルのbashプロンプトを通過し、リモートサーバーのバックスラッシュを維持すると(合計3つのバックスラッシュ:/path/to/dest/some\\\ dir/)、実際にリモートサーバーにバックスラッシュが送信されますただし、リモートサーバーはパスを/path/to/dest/some\/ではなく/path/to/dest/some\ dir/として解釈し、その後にスペースとその後の文字を削除します。

パスを引用符でラップしようとすると、パスはほぼ同じように動作し、パスをスペースで効果的に切り離します。したがって、それもローカルbashプロンプトを通過するためにのみ機能します。

最初は "-"(スペース-ハイフン-スペース)セグメントが含まれているパスを使用していて、リモートサーバーがエラーrsync: on remote machine: -: unknown optionを返していました。

では、リモートパスからスペースやハイフンなどの誤った文字を削除せずに、これをリモートサーバーで正しく機能させるにはどうすればよいですか。

10
purefusion

イニシエーターマシンで、rsyncはリモートマシンのrsyncターゲットを呼び出すコマンドラインを構築し、sshを使用してそのコマンドラインを送信します...を単一の文字列として。その単一の文字列がシェルに渡されて解析され、引数に分割されてrsyncが実行されます。 (すでに分割され、展開され、引用符で囲まれていない)引数をバイナリセーフコンテナーにリモートrsyncにパックする代わりに、なぜそれが行われるのか私にはわかりません。

つまり、引数はtwoの異なるシェル、quoteおよびrequoteによって解析されます。通常、私は各引数を二重引用符で囲み、次に式全体を単一引用符で囲みます。場合によってはそれだけでは不十分な場合や、同じ式をローカルとリモートで使用する場合は複雑になることがあります。

その場合、私は通常、いくつかのソフトリンクを単純な、スペースなし、すべてASCIIの名前で設定し、それを使用します。

9
Javier

あなたが言ったときあなたは正しい軌道に乗っていました:

同じコマンドを試して、バックスラッシュとスペースをエスケープして、ローカルbashプロンプトを通過し、リモートサーバーのバックスラッシュを維持する場合

これが私が最も簡単にできる方法です:

rsync -av dir\ with\ spaces/ server.tld:"dir\ with\ spaces"

この方法も機能します。

rsync -av dir\ with\ spaces/ server.tld:dir\\\ with\\\ spaces

正確な出力と表示されているエラーを投稿できますか?

両側のrsyncをラッパースクリプトで置き換えることはできますか?

$ Sudo su -
# cd /usr/bin
# mv rsync rsync.real
# cat <<'EOF' >rsync
#!/bin/bash
logfile=/home/yourname/rsync.log
date >> "$logfile"
i=1
for arg in "$@"; do
    echo "arg $i: $arg" >> "$logfile"
    i=$((i+1))
done

rsync.real "$@"
EOF
# chmod +x rsync

次に、もう一度rsyncを実行します。これにより、このエスケープ方法が機能することが証明されます。

クライアント側:

Sun Feb 13 13:48:12 EST 2011
1: -av
2: dir with spaces/
3: server:dir\ with\ spaces

サーバ側:

Sun Feb 13 13:48:13 EST 2011
1: --server
2: -vlogDtpre.iL
3: .
4: dir with spaces

上記の例では、サーバーの4番目の引数(dir with spaces)がすべて1行にあるという事実は、引用符が正しく機能していることを示しています。

これで問題が解決しない場合は、rsync -vrsync -vv、またはrsync -vvvを再実行してください。追加のデバッグ情報を提供します。

他の2つの愚かな提案:

  • 他のサーバーはLinuxサーバーであり、デフォルトのシェルは何ですか?
    • 多分それはあなたが期待するのとは異なる方法でファイル名を拡張しています
  • -aまたは-rオプションを追加するのを忘れましたか?
    • 私はあなたの出力を見なければ分からない
2
Mikel

ポイントの答え:

-s(保護引数)を使用し、パスを引用符で囲みます。

rsync -savz user@server:"/my path with spaces/another dir/" "/my destination/"

スペースまたはダッシュの両方で機能します。

2
Grégory Boddin