gpt4 book ai didi

bash - 为什么 bash 参数扩展会导致 rsync 命令以不同方式运行?

转载 作者:行者123 更新时间:2023-11-29 09:38:01 25 4
gpt4 key购买 nike

我正在尝试运行将文件复制到新位置的 rsync 命令。如果我直接运行 rsync 命令,没有在命令行上进行任何参数扩展,rsync 会执行我期望的操作

$ rsync -amnv --include='lib/***' --include='arm-none-eabi/include/***' \
--include='arm-none-eabi/lib/***' --include='*/' --exclude='*' \
/tmp/from/ /tmp/to/

building file list ... done
created directory /tmp/to
./
arm-none-eabi/
arm-none-eabi/include/
arm-none-eabi/include/_ansi.h
...
arm-none-eabi/lib/
arm-none-eabi/lib/aprofile-validation.specs
arm-none-eabi/lib/aprofile-ve.specs
...
lib/
lib/gcc/
lib/gcc/arm-none-eabi/
lib/gcc/arm-none-eabi/4.9.2/
lib/gcc/arm-none-eabi/4.9.2/crtbegin.o
...

sent 49421 bytes received 6363 bytes 10142.55 bytes/sec
total size is 423195472 speedup is 7586.32 (DRY RUN)

但是,如果我将过滤器参数包含在一个变量中,并使用该变量调用命令,则会观察到不同的结果。 rsync 复制了许多我期望的额外目录:

$ FILTER="--include='lib/***' --include='arm-none-eabi/include/***' \
--include='arm-none-eabi/lib/***' --include='*/' --exclude='*'"
$ rsync -amnv ${FILTER} /tmp/from/ /tmp/to/

building file list ... done
created directory /tmp/to
./
arm-none-eabi/
arm-none-eabi/bin/
arm-none-eabi/bin/ar
...
arm-none-eabi/include/
arm-none-eabi/include/_ansi.h
arm-none-eabi/include/_syslist.h
...
arm-none-eabi/lib/
arm-none-eabi/lib/aprofile-validation.specs
arm-none-eabi/lib/aprofile-ve.specs
...
bin/
bin/arm-none-eabi-addr2line
bin/arm-none-eabi-ar
...
lib/
lib/gcc/
lib/gcc/arm-none-eabi/
lib/gcc/arm-none-eabi/4.9.2/
lib/gcc/arm-none-eabi/4.9.2/crtbegin.o
...

sent 52471 bytes received 6843 bytes 16946.86 bytes/sec
total size is 832859156 speedup is 14041.53 (DRY RUN)

如果我 echo 失败的命令,它会生成准确的成功命令。复制输出,直接运行,得到了预期的结果。

关于 bash 参数扩展的工作原理,我显然遗漏了一些东西。有人可以解释为什么这两种不同的调用会产生不同的结果吗?

最佳答案

Shell 在扩展变量之前解析引号,因此将引号放入变量的值中并不会达到您的预期——当它们就位时,对它们来说做任何有用的事情都为时已晚。参见 BashFAQ #50: I'm trying to put a command in a variable, but the complex cases always fail!了解更多详情。

在您的情况下,解决此问题的最简单方法似乎是使用数组而不是纯文本变量。这样,在创建数组时会解析引号,每个“单词”都会存储为单独的数组元素,如果您正确引用变量(使用双引号和 [@]),数组元素包含在命令的参数列表中,没有任何不需要的解析:

filter=(--include='lib/***' --include='arm-none-eabi/include/***' \
--include='arm-none-eabi/lib/***' --include='*/' --exclude='*')
rsync -amnv "${filter[@]}" /tmp/from/ /tmp/to/

请注意,数组在 bash 和 zsh 中可用,但并非所有其他 POSIX 兼容的 shell。此外,我将 filter 变量名小写了——建议的做法是避免与 shell 的特殊变量(全部大写)发生冲突。

关于bash - 为什么 bash 参数扩展会导致 rsync 命令以不同方式运行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29527983/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com