转义bash变量中的特殊字符

时间:2012-02-28 13:53:59

标签: bash escaping special-characters scp

我试图逐行读取包含文件路径的文件并将文件scp到另一台服务器,但由于文件名中的某些字符如'(',') ','&'我需要逃避输入:

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 个答案:

答案 0 :(得分:9)

这里的部分问题是本地和远程文件名的解析方式不同:本地文件名是直接使用的,所以你唯一需要做的就是用双引号括起来(如@ Ignacio的回答),但是远程文件名被传递给远程shell,后者通过另一层解析(引用和转义删除等)来运行它。因此,您希望将转义添加到远程路径 。我也冒昧地简化了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'仅绕过括号和&符号;如果您的文件名包含任何其他shell元字符,请务必将它们添加到[]中的字符列表中。

答案 1 :(得分:0)

您尝试执行/folder1/folderA/filename+(oh+how+nice,+parantheses)作为命令。您可能打算改为echo /folder1/folderA/filename+(oh+how+nice,+parantheses) | ...

编辑:@Ignacio说的是什么。