8

我有一个简单的测试 bash 脚本,如下所示:

#!/bin/bash

cmd="rsync -rv --exclude '*~' ./dir ./new"
$cmd # execute command

当我运行脚本时,它也会复制以 a 结尾的文件,~即使我打算排除它们。当我直接从命令行运行相同的 rsync 命令时,它可以工作!有人知道为什么以及如何使 bash 脚本工作吗?

顺便说一句,我知道我也可以使用,--exclude-from但我想知道它是如何工作的。

4

3 回答 3

6

尝试评估

#!/bin/bash

cmd="rsync -rv --exclude '*~' ./dir ./new"
eval $cmd # execute command
于 2009-05-11T13:21:48.000 回答
5

问题不在于您在脚本中运行它,而在于您将命令放入变量中,然后运行扩展变量。而且由于在引号删除完成后会发生变量扩展,因此您的排除模式周围的单引号永远不会被删除......因此 rsync 最终会排除名称以'开头并以〜'结尾的文件。要解决此问题,只需删除模式周围的引号(整个内容已经在双引号中,因此不需要它们):

#!/bin/bash

cmd="rsync -rv --exclude *~ ./dir ./new"
$cmd # execute command

...说到这,为什么在运行命令之前将命令放入变量中?一般来说,这是一种让代码比它需要的更混乱的好方法,并触发解析异常(有些甚至比这更奇怪)。那么怎么样:

#!/bin/bash

rsync -rv --exclude '*~' ./dir ./new
于 2009-05-11T21:03:34.187 回答
0

您可以使用简单--eclude '~'的 as(根据手册页):

  • 如果模式以 / 开头,则它被锚定到文件层次结构中的特定位置,否则它与路径名的末尾匹配。这类似于正则表达式中的前导 ^。因此,“/foo”将在“传输根”(对于全局规则)或合并文件的目录(对于每个目录规则)中匹配名称“foo”。不合格的“foo”将匹配树中任何位置的“foo”名称,因为该算法是自上而下递归应用的;它的行为就像每个路径组件在文件名的末尾都有一个转折。即使是未锚定的“sub/foo”也会匹配层次结构中在名为“sub”的目录中找到“foo”的任何点。
  • 如果模式以 / 结尾,那么它将只匹配目录,而不是常规文件、符号链接或设备。
  • rsync 通过检查模式是否包含以下三个通配符之一来选择进行简单的字符串匹配和通配符匹配:'*'、'?' 和 '['。
  • '*' 匹配任何路径组件,但它在斜杠处停止。
  • 使用 '**' 匹配任何内容,包括斜线。
于 2009-05-11T11:56:56.417 回答