Экранирование специальных символов в переменных bash - PullRequest
4 голосов
/ 28 февраля 2012

Я пытаюсь прочитать файл, содержащий пути к файлам, построчно и скопировать файлы на другой сервер, но из-за определенных символов в именах файлов, таких как '(', ')', '&' и т. Д., Мне нужно экранировать вход:

input.txt

/folder1/folderA/filename+(oh+how+nice,+parantheses)

script.sh

#!/bin/sh

promote_to=random.server.com
dev_catalog=/folderX/
uat_catalog=/folderY/

while read line
do
uat_path=$(echo "$uat_catalog$line" | sed -e "s/(/\\\(/g" | sed -e "s/)/\\\)/g")
dev_path=$(echo "$dev_catalog$line" | sed -e "s/(/\\\(/g" | sed -e "s/)/\\\)/g")

scp $dev_path user@$promote_to:$uat_path
scp $dev_path".atr" user@$promote_to:$uat_path".atr"
done < "input.txt"

выход

-bash: /folder1/folderA/filename+(oh+how+nice,+parantheses): No such file or directory
-bash: /folder1/folderA/filename+(oh+how+nice,+parantheses): No such file or directory
usage: scp [-1246BCpqrv] [-c cipher] [-F ssh_config] [-i identity_file]
               [-l limit] [-o ssh_option] [-P port] [-S program]
               [[user@]host1:]file1 [...] [[user@]host2:]file2
ssh: random.server.com: Name or service not known
lost connection

Любая помощь приветствуется.

Ответы [ 2 ]

9 голосов
/ 28 февраля 2012

Часть проблемы здесь заключается в том, что локальные и удаленные имена файлов анализируются по-разному: локальное имя файла используется напрямую, поэтому единственное, что вам нужно сделать, это заключить его в двойные кавычки (как в ответе @ Ignacio), но удаленное имя файла передается в удаленную оболочку, которая запускает его через другой уровень синтаксического анализа (удаление кавычек и удаление и т. д.). Итак, вы хотите добавить escape-коды к удаленному пути только . Я также позволил себе немного упростить команду sed:

#!/bin/sh

promote_to=random.server.com
dev_catalog=/folderX/
uat_catalog=/folderY/

while read line
do
uat_path="$(echo "$uat_catalog$line" | sed -e 's/[()&]/\\&/g')"
dev_path="$dev_catalog$line"

scp "$dev_path" "user@$promote_to:$uat_path"
scp "$dev_path.atr" "user@$promote_to:$uat_path.atr"
done < "input.txt"

Обратите внимание, что шаблон sed, который я использовал, 's/[()&]/\\&/g', экранирует только скобки и амперсанды; если ваши имена файлов содержат любые другие метасимволы оболочки, обязательно добавьте их в список символов в [].

0 голосов
/ 28 февраля 2012

Вы пытаетесь выполнить /folder1/folderA/filename+(oh+how+nice,+parantheses) как команду. Вы, вероятно, хотели вместо этого сделать echo /folder1/folderA/filename+(oh+how+nice,+parantheses) | ....

Редактировать: что сказал @Ignacio.

...