首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Bash :将构建的数组作为参数列表使用?

Bash :将构建的数组作为参数列表使用?
EN

Unix & Linux用户
提问于 2018-07-31 21:40:46
回答 2查看 103关注 0票数 0

我对borgbackup有这个问题,但是由于反应是相同的,所以我将在我的示例中使用rsync

我希望通过向每个参数添加一个前缀来构建一个参数数组,然后将该数组交给rsync。但是rsync表现得好像它不存在。

使用此脚本:

代码语言:javascript
复制
#!/usr/bin/env bash
#

declare -a exclude_String
for excludestr in $(cat ./list); do
    exclude_String+=(--exclude=$excludestr)
done
rsync "${exclude_String[@]}" . $Destination

./list

代码语言:javascript
复制
'/home/*'
'*.vim*'

进程运行的ps确实正确地显示了参数:

代码语言:javascript
复制
/usr/bin/rsync --exclude='*.vim*' --exclude='/home/*' . DESTINATION

rsync仍然表现得好像他们不存在。我在这个问题上找到了这个问题,所以我试了一下:

代码语言:javascript
复制
#!/usr/bin/env bash
#

declare -a exclude_String
exclude_String+=(--exclude='/home/*')
exclude_String+=(--exclude='*.vim*')

rsync "${exclude_String[@]}" . $Destination

而且这个确实奏效了。

我还不太了解壳的扩张和其他东西,我试着引用和双引号到处都是,只是想看看我是否能找到什么,但没有运气。

你知道怎么做到这一点吗?

EN

回答 2

Unix & Linux用户

回答已采纳

发布于 2018-07-31 21:48:55

如果文件实际包含'/home/*',带有引号,则引号将在循环中的excludestr值中,然后在给rsync的参数中。在这种情况下,它们不是shell命令的一部分,只是命令替换扩展值的一部分。

另一方面,如果您编写exclude_String+=(--exclude='/home/*'),那么现在引号是shell命令的一部分,并且在处理该命令时被移除。(其效果是使*成为一个普通字符。)

rsync实际上并不期望或处理引号作为排除模式的一部分,它只是将它们视为任何其他字符,并将包含引号的文件排除在外。因此,如果将排除模式作为数据存在于某个文件中,则不应该有引号。

另外,不要使用for x in $(cat file),而是使用while IFS= read -r line; do ...; done < file,或者在本例中使用mapfile -t exclude_String < file。使用cat替换命令会调用单词拆分,因此不能有包含空格的排除模式。它还在for循环的单词列表上立即调用模式的全局化。这不是你想要的。

一般来说,你需要的是:

代码语言:javascript
复制
excludes=()
while IFS= read -r line; do 
    excludes+=(--exclude="$line")
done < ./list 
rsync "$flags" "${excludes[@]}" . "$destination"

./list只包含要排除的模式:

代码语言:javascript
复制
/home/*
*.vim*

( "$line"+=(--exclude="$line")中的引号防止shell在当前目录中使名为--exclude=something的文件全局化。)

尽管在rsync的例子中,您最好使用--exclude-from

代码语言:javascript
复制
rsync "$flags" --exclude-from=./list . "$destination"

如果要使用比文件更复杂的内容来填充循环,则可以使用进程替换:

代码语言:javascript
复制
while IFS= read -r line; do
    excludes+=(--exclude="$line")
done < <(some command that produces the exclude patterns)

另见:为什么我的变量在一个“同时读”循环中,而不是在另一个看似相似的循环中呢?

票数 2
EN

Unix & Linux用户

发布于 2018-08-01 17:55:02

正如ilkkachu所解释的,您的问题是单引号不应该是模式的一部分,如果在shell上下文中编写模式,shell将删除它们。

但是,看起来您可以不必显式地从文件中读取模式:

代码语言:javascript
复制
rsync --exclude-from=./list source/ target

使用--exclude-from=FILENAMErsync将从命名的FILENAME中读取排除模式。注意,在这样做时,模式中不应该包含那些单引号。

票数 0
EN
页面原文内容由Unix & Linux提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://unix.stackexchange.com/questions/459705

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档