【问题标题】:How can I pass a variable onto a command's parameter in a bash script?如何在 bash 脚本中将变量传递给命令的参数?
【发布时间】:2013-07-14 06:18:48
【问题描述】:

演示我的问题的示例 bash 脚本:

#!/bin/bash

function exclude
{
    BACKUP_EXCLUDES="$BACKUP_EXCLUDES --exclude=\"$1\""
}

exclude "/proc"
exclude "/dev"
exclude "/mnt"
exclude "/media"
exclude "/lost+found"

echo $BACKUP_EXCLUDES

输出:

--exclude="/proc" --exclude="/dev" --exclude="/mnt" --exclude="/media" --exclude="/lost+found"

完美!但是当我尝试添加时:

rsync -ruvz $BACKUP_EXCLUDES / /some/backup/path

$BACKUP_EXCLUDES 被完全忽略,没有错误或警告...为什么?

【问题讨论】:

标签: linux bash variables parameters rsync


【解决方案1】:

你需要使用数组:

#!/usr/bin/env bash

BACKUP_EXCLUDES=()
function exclude
{
  while
    (( $# ))
  do
    BACKUP_EXCLUDES+=(--exclude="$1")
    shift
  done
}
exclude /proc /dev /mnt /media
exclude "/lost+found"

rsync -ruvz "${BACKUP_EXCLUDES[@]}" / /some/backup/path

bash 解释:请查看@janos 答案

zsh 解释(如果是 Zsh): 当您使用字符串变量时,就像您传递了 --exclude="\"/proc\" --exclude=\"/media\" ..." - 所以它被视为带有空格的长路径 - 永远不会匹配。

【讨论】:

  • 看起来你在 while 循环上做了太多工作:for arg; do BACKUP_EXCLUDES+=(--exclude="$arg"); done
  • 我没有故意使用for $arg,因为在更大的脚本中它会使环境与arg变量混淆,为了防止它你需要先typeset arg - 最后会是再次使用相同的行数
  • 在 bash 中(shebang 暗示了这一点)它 不是 一个长字符串参数。恕我直言,zsh 行为要好得多,并且可以防止很多转义错误,但这不是问题的原因。更可能的是 janos 所说的问题。不过,您关于数组的结论是正确的,但请修正关于原因的论点。
【解决方案2】:

它不起作用,因为引号包含在单个 --exclude 参数中。也就是说,rsync 将忽略 "/proc" 而不是 /proc。当然"/proc"(带引号)不存在。

如果你在命令前面加上一个 eval,它会起作用,像这样:

eval rsync -ruvz $BACKUP_EXCLUDES / /some/backup/path

在这种情况下,--exclude="/proc"(和所有其他)将被评估为--exclude=/proc,这就是它起作用的原因。

但我认为您应该使用@mpapis 建议的数组,或评论建议的--exclude-from=FILE。两者都是更好、更清洁的解决方案。

【讨论】:

  • 感谢您对数组的解释和建议。不幸的是,我不能使用 -exclude-from,因为它与 duplicity 不兼容,而 --exclude 似乎同时适用于 rsync 和 duplicity。
猜你喜欢
  • 2012-10-21
  • 1970-01-01
  • 1970-01-01
  • 2014-09-13
  • 1970-01-01
  • 2016-05-31
  • 2013-10-11
  • 2018-07-23
  • 1970-01-01
相关资源
最近更新 更多