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

Как правильно избежать шаблона исключения rsync, используемого в сценарии bash?

Сценарий:

#!/bin/bash

site=$1
remote_host=$2
new_site=${3:-$1}

cmd="rsync -rlpuvz -e ssh /www/$site/ $remote_host:/www/$new_site --force --delete --exclude=\"site/web_sitemap_*.xml.gz\""
echo $cmd
$cmd

Вывод скрипта:

[xxx@xxx ~]$ rsync -rlpuvz -e ssh /www/xxx/ xxx:/www/xxx --force --delete --exclude="site/web_sitemap_*.xml.gz"

sending incremental file list
deleting site/web_sitemap_ff3abe06_000.xml.gz

Вроде лечит цитаты \" как буквальный " имя файла / символы шаблона. Я получаю то же самое с одинарными кавычками (без экранирования) ' как в "--exclude='site/web_sitemap_*.xml.gz'". ОДНАКО, если мы попробуем то же самое без каких-либо встроенных кавычек, это сработает! Версия без цитирования:

[xxx@xxx ~]$ touch /www/xxx/site/web_sitemap_ff3abe06_000.xml.gz

[xxx@xxx ~]$ rsync -rlpuvz -e ssh /www/xxx/ xxx:/www/xxx --force --delete --exclude=site/web_sitemap_*.xml.gz

sending incremental file list

sent 41624 bytes  received 290 bytes  7620.73 bytes/sec
total size is 18233892  speedup is 435.03

Отказ от кавычек кажется ответом, но тогда как мне защититься от расширения оболочки или интерпретации специальных символов в случаях, когда шаблон исключения rsync содержит символы, которые обычно расширяются или интерпретируются bash (например, : или ; или \ или [)?

Вы должны прочитать BashFAQ / 050 aka Я пытаюсь ввести команду в переменную, но сложные случаи всегда терпят неудачу!.

TL; DR:

Это не удается, потому что [...] кавычки [...] внутри переменной буквальны; не синтаксический.

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

Как только вы прочитали #050 вы можете переоценить, если вам это действительно нужно. Если вы все еще думаете, что это так, и решите проигнорировать совет против этого, вы захотите сохранить свою команду в массиве:

cmd=( rsync -rlpuvz -e ssh "/www/${site}/" "${remote_host}:/www/${new_site}" --force --delete --exclude="site/web_sitemap_*.xml.gz" )
"${cmd[@]}"