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

10

При использовании 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/удаляет пробел и символы после него.

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

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

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

purefusion
источник
1
Попробуйте как одинарные, так и двойные кавычки.
Jftuga
Хавьер тоже об этом упомянул, и в итоге все заработало, поэтому я вставил свой сегмент рабочего кода в ответ на его ответ.
чистое слияние
@purefusion Подумайте о том, чтобы пометить ответ Грегори как правильный. В -sрассматривается вопрос без необходимости применять двойной побег вручную.
m000

Ответы:

9

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

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

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

Хавьер
источник
8
И победителем становится ... одинарные + двойные кавычки! Может быть, это отличается на каждом сервере, поэтому, если другие ответы не работают для некоторых людей, возможно, этот будет работать. Вот успешный код, который я использовал на удаленной стороне команды rsync:'user@host.tld:"/path/to/dest/some\ dir/"'
purefusion
Теперь возникает вопрос, почему ЭТО работает (на моем сервере), но не любой из других вариантов (просто заключая путь в двойные кавычки или используя тройные обратные слэши)? Я использую CentOS 5, если это имеет значение.
чистое слияние
Это не должно быть необходимым. Как ты это делаешь? Вы используете его evalили, возможно, через вызов функции?
Микель
Вы не используете одинарные плюс двойные кавычки. Вы используете одинарные кавычки плюс двойные кавычки плюс обратные слэши. ТРИ уровня цитирования. Это должно быть ненужным. Я снова спрашиваю: как у вас это работает ?
Микель
@ Хавьер "Я понятия не имею, почему это сделано". Предположительно так, что расширение тильды работает.
Микель
2

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

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

Вот способ, которым я нахожу самый простой способ сделать это:

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-й аргумент server ( dir with spaces) находится в одной строке, говорит о том, что цитирование работает правильно.

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

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

  • другой сервер - сервер Linux, и какая у вас оболочка по умолчанию?
    • может быть, он расширяет имена файлов не так, как вы ожидаете
  • Вы забыли добавить опцию -aили -r?
    • Я не могу сказать, не видя ваш вывод
Mikel
источник
Как уже упоминалось в деталях вопроса, я действительно попробовал оба ваших первых двух метода. Возможно, они просто не работают на моем сервере. Мне также не хотелось возиться со скриптами-обертками. Я стараюсь держаться подальше от взлома / usr / bin / ... В любом случае, другой, более конкретный способ цитирования действительно сработал для меня, так что, возможно, так действует только мой сервер. Ваши предложения все еще могут быть полезны для людей на других серверах или для тех, кто не работает под CentOS, если в конце концов ОС является частью проблемы.
purefusion
Итак, как вы процитировали это, чтобы оно заработало?
Микель
Вы упускаете некоторые важные детали. Пожалуйста, опубликуйте фактическую команду, которую вы выполняете, полностью.
Микель
2

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

Используйте -s (protect args) и заключите ваш путь в кавычки:

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

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

Грегори Боддин
источник
Спасибо! Это правильное решение, а не обходной путь.
m000
-2

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

АТХ
источник
1
Как вы могли видеть в деталях вопроса, я действительно уже пробовал это. Однако другой ответ предложил конкретное использование цитаты, и это действительно сработало. :)
purefusion
Вам нужны ОБА цитаты и обратный слеш.
Шридхар Сарнобат