Назад | Перейти на главную страницу

Экранирование пробелов в удаленном пути при использовании rsync через удаленное соединение SSH

При использовании SSH для подключения rsync к удаленному серверу, как избежать пробелов и т.п. на удаленном пути? Простая обратная косая черта убирает пробел для локального приглашения bash, но на удаленной машине пробел затем читается как разрыв в пути, тем самым отмечая конец этого пути.

Итак, когда я это сделаю rsync -avz /path/to/source/some\ dir/ user@host.tld:/path/to/dest/some\ dir/ происходит то, что удаленный сервер читает это как /path/to/dest/some/ и поскольку он не может найти это место назначения удаленно, потому что фактическим местом назначения является «некоторый каталог», а не просто «какой-то».

Если я попробую ту же команду и избегу обратной косой черты и пробела, чтобы пропустить локальную подсказку bash и сохранить обратную косую черту для удаленного сервера (всего три обратной косой черты: /path/to/dest/some\\\ dir/), он действительно отправляет обратную косую черту на удаленный сервер, но удаленный сервер затем интерпретирует путь как /path/to/dest/some\/ скорее, чем /path/to/dest/some\ dir/ все еще удаляя пробел и символы после него.

Если я попытаюсь заключить путь в кавычки, он будет вести себя примерно так же, фактически обрезая путь в пространстве. Так что это тоже работает, только чтобы обойти локальную подсказку bash.

Изначально я использовал путь, в котором был сегмент «-» (пробел-дефис-пробел), и удаленный сервер возвращал ошибку rsync: on remote machine: -: unknown option именно с этого в первую очередь началось все это стремление к побегу из космоса.

Итак, что я должен сделать, чтобы это работало правильно с удаленным сервером, без необходимости удалять пробелы или другие ошибочные символы, такие как дефисы, с удаленного пути?

На машине-инициаторе rsync создает командную строку, которая вызывает цель rsync на удаленном компьютере, а затем отправляет эту командную строку с помощью ssh .... как одна строка. Эта единственная строка передается в оболочку для анализа, разделения на аргументы и выполнения. rsync. Я понятия не имею, почему это делается, вместо того, чтобы упаковать аргументы (уже разделенные, развернутые и не заключенные в кавычки) в какой-то бинарно-безопасный контейнер для удаленного rsync.

Это означает, что ваши аргументы будут проанализированы два разные снаряды, цитата и реквотировать соответственно. Обычно я заключаю каждый аргумент в двойные кавычки, а затем все выражение в одинарные кавычки. иногда этого недостаточно или это может быть сложно, если вы хотите, чтобы одно и то же выражение использовалось локально и удаленно.

В таких случаях я обычно устанавливаю некоторые программные ссылки с простыми именами без пробелов и полностью в формате ASCII и использую их.

Точечный ответ:

Используйте -s (защитить аргументы) и заключите свой путь в кавычки:

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

Работает как с пробелами, так и с дефисами.

Вы были на правильном пути, когда сказали:

Если я попробую ту же команду и избегу обратной косой черты и пробела, чтобы пропустить локальную подсказку 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) в одной строке говорит о том, что цитирование работает правильно.

Если это не помогает, попробуйте перезапустить rsync -v, или rsync -vv, или rsync -vvv. Это даст вам дополнительную отладочную информацию.

Два других глупых предложения:

  • другой сервер является сервером Linux, и какая у вас там оболочка по умолчанию?
    • возможно, он расширяет имена файлов иначе, чем вы ожидаете
  • ты забыл добавить -a или -r вариант?
    • Я не могу сказать, не увидев вашего вывода

Вы можете просто заключить свой путь в кавычки.