Bash:需要帮助将变量传递给rsync

时间:2018-06-05 23:54:24

标签: bash variables rsync

我希望将 $ home 作为要在运行 rsync 时排除的目录列表。文件:

cat backup_system.sh
#!/bin/bash
set -x
home=''
home=$home'"/home/ravas/Documents/*"',
home=$home'"/home/ravas/Downloads/*"',
home=$home'"/home/ravas/pCloudDrive/*"',
home=$home'"/home/ravas/pCloudLocal/*"',
home=$home'"/home/ravas.old/*"'
echo $home
sudo rsync -aAXv / --exclude={$home,"/dev/*","/proc/*","/sys/*","/tmp/*","/run/*","/mnt/*","/media/*","/lost+found"} /run/media/ravas/system_backup

备份在没有 $ home 变量的情况下运行良好,但如果我添加它,它就不会有任何影响。

输出的最后两行显示 $ home 中列出的目录未使用 - exclude 进行扩展,而其他目录则是。

毋庸置疑,我不太擅长bash,任何帮助都会非常感激!

./backup_system.sh 
+ home=
+ home='"/home/ravas/Documents/*",'
+ home='"/home/ravas/Documents/*","/home/ravas/Downloads/*",'
+ home='"/home/ravas/Documents/*","/home/ravas/Downloads/*","/home/ravas/pCloudDrive/*",'
+ home='"/home/ravas/Documents/*","/home/ravas/Downloads/*","/home/ravas/pCloudDrive/*","/home/ravas/pCloudLocal/*",'
+ home='"/home/ravas/Documents/*","/home/ravas/Downloads/*","/home/ravas/pCloudDrive/*","/home/ravas/pCloudLocal/*","/home/ravas.old/*"'
+ echo '"/home/ravas/Documents/*","/home/ravas/Downloads/*","/home/ravas/pCloudDrive/*","/home/ravas/pCloudLocal/*","/home/ravas.old/*"'
"/home/ravas/Documents/*","/home/ravas/Downloads/*","/home/ravas/pCloudDrive/*","/home/ravas/pCloudLocal/*","/home/ravas.old/*"
+ sudo rsync -aAXv / 
'--exclude="/home/ravas/Documents/*","/home/ravas/Downloads/*","/home/ravas/pCloudDrive/*","/home/ravas/pCloudLocal/*","/home/ravas.old/*"' 
'--exclude=/dev/*' '--exclude=/proc/*' '--exclude=/sys/*' '--exclude=/tmp/*' '--exclude=/run/*' '--exclude=/mnt/*' '--exclude=/media/*' --exclude=/lost+found** /run/media/ravas/system_backup

3 个答案:

答案 0 :(得分:3)

几乎所有与多参数相关的问题的解决方案是使用数组:

exclusions=(
  --exclude "/home/ravas/Documents/*"
  --exclude "/home/ravas/Downloads/*"
  --exclude "/home/ravas/pCloudDrive/*"
  --exclude "/home/ravas/pCloudLocal/*"
  --exclude "/home/ravas.old/*"
  --exclude "/dev/*"
  --exclude "/proc/*"
  --exclude "/sys/*"
  --exclude "/tmp/*"
  --exclude "/run/*" 
  --exclude "/mnt/*"
  --exclude "/media/*"
  --exclude "/lost+found"
)

sudo rsync -aAXv / "${exclusions[@]}" /run/media/ravas/system_backup

如果您没有使用标准输入进行其他操作,可以将--exclude-from选项与here文档一起使用以缩短此位:

sudo rsync -aAXv / --exclude-from - /run/media/ravas/system_backup <<EOF
/home/ravas/Documents/*
/home/ravas/Downloads/*
/home/ravas/pCloudDrive/*
/home/ravas/pCloudLocal/*
/home/ravas.old/*
/dev/*
/proc/*
/sys/*
/tmp/*
/run/* 
/mnt/*
/media/*
/lost+found
EOF

答案 1 :(得分:1)

基本问题是bash在你的命令中解析各种事情的顺序对你正在尝试做的事情都是错误的。具体来说,它解析(并应用和删除)引号和&amp;转义,然后展开{this,that,theother}列表,然后展开变量引用(如$home)。最终结果是,当$home扩展为逗号分隔的引用元素列表时,引号或逗号的预期效果为时已晚。

像往常一样,数组是解决这个问题的最好方法:

homearray=()
homearray+=("/home/ravas/Documents/*")
homearray+=("/home/ravas/Downloads/*")
homearray+=("/home/ravas/pCloudDrive/*")
homearray+=("/home/ravas/pCloudLocal/*")
homearray+=("/home/ravas.old/*")
# Alternate short form:
# homearray=(/home/ravas/{Documents,Downloads,pCloudDrive,pCloudLocal}/"*" "/home/ravas.old/*")
sudo rsync -aAXv / "${homearray[@]/#/--exclude=}" --exclude={"/dev/*","/proc/*","/sys/*","/tmp/*","/run/*","/mnt/*","/media/*","/lost+found"} /run/media/ravas/system_backup

说明:"${homearray[@]/#/--exclude=}"做三件事;首先,[@]使它扩展到数组的所有元素;然后/#/--exclude=&#34;替换&#34;每个元素的开头有&#34; - exclude =&#34; (基本上,它预先&#34; - 排除=&#34;到每个元素),最后它周围的双引号使通配符(&#34; *&#34;)不会扩展并造成严重破坏。

答案 2 :(得分:0)

Bash中的字符串处理很少直截了当,但这里的内容很有用......

( list=abc,'"def\ ghi"',jkl ; eval echo --exclude={$list} )

输出:

--exclude=abc --exclude=def\ ghi --exclude=jkl

请参阅eval command in Bash and its typical uses