我有一个bash脚本(cygwin),它使用一些带有空格的窗口路径。因此,我在变量定义中使用\来逃避空间。脚本中的所有内容都可以正常工作。但是,我需要将此变量作为参数传递给命令行可执行文件。当我这样做时,我的逃避就搞砸了。
示例非功能性脚本:
#!/bin/sh
# file paths
destinationPath="/cygdrive/c/Documents and Settings/Eric/My Documents/"
attachments="\n2013-12-12.pdf"
body="Test Body"
recipient="asdf@asdf.com"
# prepare attachments
args=""
for file in $attachments ; do
file=${file//[ \\n]/}
touch $file
mv $file "$destinationPath/$file"
args="$args -a $destinationPath/$file"
done
# send email
echo -e $body | email --from-addr nosender@mydomain.com --from-name "Automated CSS Downloader" --subject "Downloaded new file(s) \
from CSS" $args eric@mydomain.com
脚本输出:
$ bash -x test.sh
+ destinationPath='/cygdrive/c/Documents and Settings/Eric/My Documents/'
+ attachments='\n2013-12-12.pdf'
+ body='Test Body'
+ recipient=asdf@asdf.com
+ args=
+ for file in '$attachments'
+ file=2013-12-12.pdf
+ touch 2013-12-12.pdf
+ mv 2013-12-12.pdf '/cygdrive/c/Documents and Settings/Eric/My Documents//2013-12-12.pdf'
mv: listing attributes of `2013-12-12.pdf': Invalid argument
+ args=' -a /cygdrive/c/Documents and Settings/Eric/My Documents//2013-12-12.pdf'
+ echo -e Test Body
+ email --from-addr nosender@mydomain.com --from-name 'Automated CSS Downloader' --subject 'Downloaded new file(s) from CSS' -a /cygdrive/c/Documents and Settings/Eric/My Documents//2013-12-12.pdf eric@mydomain.com
email: WARNING: Email address 'and' is invalid. Skipping...
email: FATAL: Could not open attachment: /cygdrive/c/Documents: No such file or directory
因此,您可以看到路径中的转义空间未在$ args变量中导出。我假设错误出现在“args = ...”行。但我不确定如何转义$ destinationPath以确保保留转义字符。
我尝试在destinationPath中使用双引号(没有转义空格),但无济于事。如果我尝试在args =行中双引号$ destinationPath,那么输出也会被一堆额外的引用所搞砸。
我怎样才能让它发挥作用?我试过玩$ IFS变量,但我真的不知道我用它做了什么,似乎也无法使用它,尽管我怀疑解决方案与之有关$ IFS。
答案 0 :(得分:5)
没有数组就没有好办法做到这一点。 (使用eval
有一种不太好的方法,但数组更简单。)
问题是你希望每个文件最终作为email
的一个参数,但你想将所有这些参数累积到一个bash变量中。没有办法做到这一点:你可以使bash变量作为单个参数("$arg"
)插入,或者你可以插入它,因为它被分成许多单词($arg
),但是你不能根据创建变量时是否转义空格来分割它,因为bash只会记住分配给变量的字符串,而不是转义符。
但是,您可以使用数组,因为您可以使每个文件名恰好是一个数组元素,并且您可以使用bash将数组作为每个元素的一个参数插入。
以下是:
# file paths
destinationPath="/cygdrive/c/Documents and Settings/Eric/My Documents/"
attachments="\n2013-12-12.pdf"
body="Test Body"
recipient="asdf@asdf.com"
# prepare attachments
args=()
for file in $attachments ; do
file=${file//[ \\n]/}
touch $file
mv $file "$destinationPath/$file"
args+=(-a "$destinationPath/$file")
done
# send email
echo -e $body |
email --from-addr nosender@mydomain.com \
--from-name "Automated CSS Downloader" \
--subject "Downloaded new file(s) from CSS" \
"${args[@]}" eric@mydomain.com
您可能还想将attachments
变量放入数组中;从换行符的存在,我假设你实际上是以一种更复杂的方式设置它,所以我没有更改代码。但是如果附件名称中有空格,那么您当前的代码将无效(我非常确定新行将通过for
形式的参数扩展来消除,除非您更改了值$IFS
的{{1}},所以file=${file//[ \\n]/}
不是必需的。)
答案 1 :(得分:0)
在字符串中提供destinationPath时,您需要转义双引号。
这应该有效:
#!/bin/sh
# file paths
destinationPath="/cygdrive/c/Documents and Settings/Eric/My Documents/"
attachments="\n2013-12-12.pdf"
body="Test Body"
recipient="asdf@asdf.com"
# prepare attachments
args=""
for file in $attachments ; do
file=${file//[ \\n]/}
touch $file
mv $file "$destinationPath/$file"
#HERE YOU NEED ESCAPED DOUBLEQUOTED
args="$args -a \"$destinationPath/$file\""
done
# send email
echo -e $body | email --from-addr nosender@mydomain.com --from-name "Automated CSS Downloader" --subject "Downloaded new file(s) \
from CSS" $args eric@mydomain.com