kiw*_*san 1 variables bash shell substitution
我正在尝试通过从外部文件中读取值并在它们前面加上-x. 将有不同数量的排除项,包括根本没有排除项。我遇到的问题是当 bash 扩展这个变量时,它用单引号将它框起来。这会混淆备份脚本。
#cat sss2.sh:
#!/bin/bash
IFS=$'\n'
xcl=""
for x in $(cat /root/exfile)
do
xcl="$xcl -x $x"
done
backupbin /sourcepath /destination "$xcl"
# cat exfile
"*.tgz"
"*.zip"
Run Code Online (Sandbox Code Playgroud)
当我运行它时,bash$xcl用单引号扩展变量,这会阻止backupbin运行。这是由于空格,因为如果我没有-x,单引号就会消失。
# /bin/bash -x ./sss2
+ IFS=''
+ xcl=
++ cat exfile
+ for x in '$(cat /root/exfile)'
+ xcl=' -x "*.tgz"'
+ for x in '$(cat exfile)'
+ backupbin /sourcepath /destination ' -x "*.tgz" -x "*.zip"'
Run Code Online (Sandbox Code Playgroud)
我曾尝试将其作为扩展填充数组,并尝试过单引号、双引号和反引号的不同组合。我试过使用 eval 没有成功:
backupbin /sourcepath /destination $(eval echo "$xcl")
Run Code Online (Sandbox Code Playgroud)
最后,我尝试创建一个数组并扩展它,但得到相同的结果:
IFS=$'\n'
excludefile=($(cat /root/exfile))
if [ ${#excludefile[@]} -eq 0 ]; then
echo ""
else
for i in "${excludefile[@]}"
do
printf "%s" " -x $i"
done
Run Code Online (Sandbox Code Playgroud)
我究竟做错了什么?
与此类问题一样,此类问题的最简单解决方案是使用数组,而不是尝试处理引号。(引用+评估解决方案在某些极端情况下几乎总是失败,有时是灾难性的。)
#!/bin/bash
IFS=$'\n'
xcl=()
for x in $(< /root/exfile); do
xcl+=(-x "$x")
done
backupbin /sourcepath /destination "${xcl[@]}"
Run Code Online (Sandbox Code Playgroud)
请参阅bash 常见问题解答。
编辑:正如@konsolebox 所指出的, 的使用$(</root/exfile)受路径名扩展的影响。因此,如果文件包含像“foo*”这样的行foo,并且当前工作目录中存在一个或多个名称以文件名列表。最好使用:
#!/bin/bash
xcl=()
while IFS= read -r x; do xcl+=(-x "$x"); done < /root/exfile
backupbin /sourcepath /destination "${xcl[@]}"
Run Code Online (Sandbox Code Playgroud)