【问题标题】:Variable substitution not working to pass --exclude options to tar command变量替换无法将 --exclude 选项传递给 tar 命令
【发布时间】:2022-01-11 14:01:25
【问题描述】:

我正在尝试通过 env var 将一些 --exclude 语句传递给我的 tar 命令(实际上我会传递几个 --exclude 语句,并试图通过将定义放在单独的行上来提高可读性) :

# EXCLUDE_STUFF="--exclude='/captain/generated'"
# tar ${EXCLUDE_STUFF} -cvzf /dev/null /captain
/captain/
/captain/generated/
/captain/generated/registry-auth
... etc ...

即它不排除我指定的文件夹。如果我用引号将${EXCLUDE_STUFF} 括起来并没有什么不同。

这是我回显上述命令时得到的结果:

# echo tar ${EXCLUDE_STUFF} -cvzf /dev/null /captain
tar --exclude='/captain/generated' -cvzf /dev/null /captain

所以看起来命令是正确的。当我直接运行扩展命令时,我得到:

# tar --exclude='/captain/generated' -cvzf /dev/null /captain
/captain/
/captain/temp/
/captain/data/
... etc ...

即指定的文件夹被排除。

那么为什么变量替换在这种情况下不起作用?

【问题讨论】:

    标签: linux unix environment-variables tar


    【解决方案1】:

    为什么变量替换在这种情况下不起作用?

    赋值后变量EXCLUDE_STUFF包含字面意思字符串--exclude='/captain/generated'

    您正在通过变量替换传递--exclude='/captain/generated'。因为相对于您当前的工作目录,没有名为 literally ' 的目录,'/captain/generated' 不匹配任何内容,因此它不排除任何内容。

    总之tar --exclude='/captain/generated'tar "--exclude='/captain/generated'"是不一样的。

    在这种情况下,只是

    exclude_stuff="--exclude=/captain/generated"
    tar "$exclude_stuff" ...
    

    或者使用 bash 数组:

    exclude_stuff=( --exclude='/captain/generated' )  # note: quotes are interpreted
    tar "${exclude_stuff[@]}" ...
    

    阅读https://mywiki.wooledge.org/BashFAQ/050。研究 shell 引用,它是如何工作的,以及何时使用它,研究分词扩展和文件名扩展。使用 https://shellcheck.net 检查您的脚本。脚本局部变量更喜欢使用小写变量。

    【讨论】:

    • 这个答案真的很有帮助,谢谢。让我有点困惑的是单引号的存在与任何内容都不匹配,因此它不排除任何内容....但tar 的文档建议将排除模式用单引号括起来:gnu.org/software/tar/manual/html_node/… .. . 以及为什么直接运行命令时它会起作用(没有变量替换但包含单引号)?那么是否正在运行两个不同的命令(带变量/不带变量)?
    • 另外,tar "$exclude_stuff" 不起作用……但 tar $exclude_stuff 起作用。
    • 你说It doesn't make a difference if I surround ${EXCLUDE_STUFF} in quotes。将set -x 添加到您的脚本中,看看发生了什么。研究如何调试 bash 脚本。 tar suggest wrapping the exclude pattern in single quotes在哪里? why does it work when you run the command directly... 因为变量中包含字符',所以直接将引号解释为shell 解析的一部分。echo "stuff"echo "'stuff'"a="'stuff'" ; echo $a 之间存在差异。请研究shell引用。 are two different... 是的。
    • 好的,谢谢...看起来需要进行更多研究...关于“tar 建议将排除模式用单引号括起来——在哪里?”...我包含在链接中的示例我的第一条评论将排除模式用单引号括起来。
    • 是的,--exclude='*.o' 被包装以防止 shell 进行文件名扩展。引号被 shell 删除,然后 --exclude=*.o 被传递给 tar。在命令前添加set -x,看看实际执行了什么。
    猜你喜欢
    • 2015-02-15
    • 2019-02-16
    • 2017-12-15
    • 2012-06-24
    • 1970-01-01
    • 2017-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多