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


10

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

つまり、実際に宛先が「一部」ではなく「一部のディレクトリ」であるため、rsync -avz /path/to/source/some\ dir/ user@host.tld:/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を返していましたが、そもそもこのスペースをエスケープする作業全体が開始されました。

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


1
一重引用符と二重引用符の両方を試してください。
-jftuga

ハビエルもこれに言及し、それが機能するようになったので、彼の答えへの返信に私の作業コードセグメントを貼り付けました。
purefusion、2011

@purefusionグレゴリーの答えを正しいものとしてマークすることを検討してください。-sダブルエスケープ手動で適用する必要のないアドレスの問題。
m000

回答:


9

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

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

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


8
そして勝者は...一重引用符と二重引用符です!たぶん、これはすべてのサーバーで異なるので、他の回答が一部の人にとってうまくいかない場合、おそらくこれがうまくいくでしょう。ここで私はrsyncのコマンドのリモート側で使用成功コードは次のとおりです。'user@host.tld:"/path/to/dest/some\ dir/"'
purefusion

ここで質問をお願いします、なぜこれは(私のサーバーで)機能しますが、他のオプションのどちらも機能しません(パスを二重引用符で囲むか、トリプルバックスラッシュを使用します)?それが重要であれば、私はCentOS 5を実行しています。
purefusion、2011

それは必要ないはずです。どのように実行していますか?eval関数を使用して、または関数の呼び出しを介して実行していますか?
ミケル

一重引用符と二重引用符を使用していません。一重引用符と二重引用符とバックスラッシュエスケープを使用しています。3つのレベルの引用。これは不要です。もう一度質問します。どのように実行していますか?
ミケル

@Javier「なぜそれが行われるのか私にはわからない」。おそらくチルダ拡張が機能するように。
ミケル

2

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

同じコマンドを試してバックスラッシュとスペースをエスケープして、ローカルの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

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

これがないヘルプがない場合、再実行してみてくださいrsync -v、またはrsync -vv、またはrsync -vvv。追加のデバッグ情報を提供します。

他の2つの愚かな提案:

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

質問の詳細で述べたように、私は確かに最初の2つの方法の両方を試しました。おそらく、それらは私のサーバーでは機能しません。また、ラッパースクリプトをいじりたくありませんでした。私は/ usr / bin /をハッキングしないようにしています...いずれにせよ、もう1つのより具体的な引用方法が実際に機能しました。おそらく、このように動作しているのはサーバーだけです。結局のところ、OSが問題の一部である場合は、他のサーバーを使用している人やCentOSを実行していない人にとって、提案は確かに実行可能である可能性があります。
purefusion、2011

それで、それを機能させるためにどのようにそれを引用しましたか?
ミケル

あなたはいくつかの重要な詳細を省いています。実行している実際のコマンドを完全に投稿してください。
ミケル

2

ポイントの答え:

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

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

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


ありがとう!これは回避策というよりは適切な解決策です。
m000

-2

パスを引用符で囲むことができます。


1
あなたが質問の詳細で見たかもしれないように、私は確かにこれをすでに試しました。しかし、別の答えは特定の引用の使用法を示唆しており、それは実際に最終的に機能しました。:)
purefusion '13

引用符とバックスラッシュの両方が必要です。
Sridhar Sarnobat
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.