我试图为bash上的备份脚本生成一个命令行。
简单的例子:
EXCLUDES="/home/*/.cache/* /var/cache/* /var/tmp/* /var/lib/lxcfs/cgroup/*";
for FOLDER in $EXCLUDES; do printf -- '--exclude %b\n' "$FOLDER" ; done应导致:
--exclude '/home/*/.cache/*' --exclude '/var/cache/*' --exclude '/var/tmp/*' --exclude '/var/lib/lxcfs/cgroup/*'但问题是,文件夹是从shell中展开的。我试过很多例子,比如echo / printf /引文/IFS.但没有正确的结果。
有办法解决这个问题吗?
发布于 2018-07-03 18:22:57
每当您必须用文件名globs指定路径名或路径名的列表时,或者通常只指定要循环的列表和/或将其用作某个命令的参数列表时,请使用数组。
如果不使用数组,而使用字符串,则无法处理其中包含空格的事情(因为您在字符串中使用空格作为分隔符)。它还使您很难循环字符串的内容,因为您将不得不调用单词拆分(通过不引用变量展开)。但是,这也会导致文件名全局化的发生,除非您在set -f中显式地关闭它。
在大多数shell中,即使在普通的/bin/sh中,也要使用数组。在sh中,使用位置参数数组($@)。
对于bash,使用一个引号字符串数组,如
excludes=( '/home/*/.cache/*'
'/var/cache/*'
'/var/tmp/*'
'/var/lib/lxcfs/cgroup/*' )然后,
rsync_opts=( --verbose --archive )
for excl in "${excludes[@]}"; do
rsync_opts+=( --exclude="$excl" )
done后来,
rsync "${rsync_opts[@]}" source/ target请注意,引号在上述所有变量展开中都很重要。展开"${array[@]}" (以及下面的"$@" )将生成一个单独引用的数组元素列表(但只有在双引用的情况下!)。
对于任何/bin/sh外壳:
set -- '/home/*/.cache/*' \
'/var/cache/*' \
'/var/tmp/*' \
'/var/lib/lxcfs/cgroup/*'
for excl do
set -- "$@" --exclude="$excl"
shift
done
set -- --verbose --archive "$@"
rsync "$@" source/ targethttps://unix.stackexchange.com/questions/453276
复制相似问题