为什么bash参数扩展会导致rsync命令以不同的方式运行? [英] Why do bash parameter expansions cause an rsync command to operate differently?

查看:51
本文介绍了为什么bash参数扩展会导致rsync命令以不同的方式运行?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am attempting to run an rsync command that will copy files to a new location. If I run the rsync command directly, without any parameter expansions on the command line, rsync does what I expect

$ 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 复制了许多我期望的额外目录:

However, if I enclose the filter arguments in a variable, and invoke the command using that variable, different results are observed. rsync copies over a number of extra directories I do not expect:

$ 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 失败的命令,它将生成成功的确切命令.复制输出并直接运行会给我预期的结果.

If I echo the command that fails, it generates the exact command that succeeds. Copying the output, and running directly gives me the expected result.

关于bash参数扩展的工作方式,我显然缺少一些东西.有人可以解释为什么两个不同的调用产生不同的结果吗?

There is obviously something I'm missing about how bash parameter expansion works. Can somebody please explain why the two different invocations produce different results?

推荐答案

Shell会在扩展变量之前先分析引号,因此将引号放入变量的值并不能满足您的期望-到位时,他们做任何有用的事情为时已晚.请参见 BashFAQ#50:我试图将命令放入变量中,但是复杂的情况总是会失败!/a>了解更多信息.

The shell parses quotes before expanding variables, so putting quotes in a variable's value doesn't do what you expect -- by the time they're in place, it's too late for them to do anything useful. See BashFAQ #50: I'm trying to put a command in a variable, but the complex cases always fail! for more details.

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

In your case, it looks like the easiest way around this problem is to use an array rather than a plain text variable. This way, the quotes get parsed when the array is created, each "word" gets stored as a separate array element, and if you reference the variable properly (with double-quotes and [@]), the array elements get included in the command's argument list without any unwanted parsing:

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兼容外壳程序都可用.另外,我将 filter 变量名小写-建议的做法是避免与shell的特殊变量(大写)冲突.

Note that arrays are available in bash and zsh, but not all other POSIX-compatible shells. Also, I lowercased the filter variable name -- recommended practice to avoid colliding with the shell's special variables (which are all uppercase).

这篇关于为什么bash参数扩展会导致rsync命令以不同的方式运行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆