脚本文件与命令行:rsync 和 --exclude

发布于 2024-07-18 16:57:18 字数 319 浏览 5 评论 0原文

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

#!/bin/bash

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

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

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

I have a simple test bash script which looks like that:

#!/bin/bash

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

When I run the script it will copy also the files ending with a ~ even though I meant to exclude them. When I run the very same rsync command directly from the command line, it works! Does someone know why and how to make bash script work?

Btw, I know that I can also work with --exclude-from but I want to know how this works anyway.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

若言繁花未落 2024-07-25 16:57:18

尝试评估

#!/bin/bash

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

Try eval:

#!/bin/bash

cmd="rsync -rv --exclude '*~' ./dir ./new"
eval $cmd # execute command
国粹 2024-07-25 16:57:18

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

#!/bin/bash

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

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

#!/bin/bash

rsync -rv --exclude '*~' ./dir ./new

The problem isn't that you're running it in a script, it's that you put the command in a variable and then run the expanded variable. And since variable expansion happens after quote removal has already been done, the single quotes around your exclude pattern never get removed... and so rsync winds up excluding files with names starting with ' and ending with ~'. To fix this, just remove the quotes around the pattern (the whole thing is already in double-quotes, so they aren't needed):

#!/bin/bash

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

...speaking of which, why are you putting the command in a variable before running it? In general, this is a good way make code more confusing than it needs to be, and trigger parsing oddities (some even weirder than this). So how about:

#!/bin/bash

rsync -rv --exclude '*~' ./dir ./new
江湖彼岸 2024-07-25 16:57:18

您可以使用简单的 --einclude '~' 作为(根据手册页):

  • 如果模式以 / 开头,则它被锚定到
    文件的层次结构,否则
    与结尾匹配
    路径名。 这类似于领先的
    ^ 在正则表达式中。 因此“/foo”
    将匹配“foo”的名称
    “传输的根”(对于
    全局规则)或在合并文件中
    目录(对于每个目录的规则)。
    不合格的“foo”将匹配
    树中任意位置的“foo”名称
    因为应用了算法
    从上到下递归; 它
    行为就好像每个路径组件都得到
    结束时的转折
    文件名。 即使是无锚的
    “sub/foo”将在任何点匹配
    找到“foo”的层次结构
    在名为“sub”的目录中。 看
    锚定部分
    包含/排除完整的模式
    讨论如何指定模式
    与根匹配
    转移。
  • 如果模式以 / 结尾,那么它将仅匹配目录,而不匹配
    常规文件、符号链接或设备。
  • rsync 在简单字符串匹配和通配符之间进行选择
    通过检查模式是否匹配
    包含这三个通配符之一
    字符:“*”、“?”和“[”。
  • “*”匹配任何路径组件,但它在斜杠处停止。
  • 使用“**”来匹配任何内容,包括斜杠。

You can use a simple --eclude '~' as (accoding to the man page):

  • if the pattern starts with a / then it is anchored to a particular spot in
    the hierarchy of files, otherwise it
    is matched against the end of the
    pathname. This is similar to a leading
    ^ in regular expressions. Thus "/foo"
    would match a name of "foo" at either
    the "root of the transfer" (for a
    global rule) or in the merge-file's
    directory (for a per-directory rule).
    An unqualified "foo" would match a
    name of "foo" anywhere in the tree
    because the algorithm is applied
    recursively from the top down; it
    behaves as if each path component gets
    a turn at being the end of the
    filename. Even the unanchored
    "sub/foo" would match at any point in
    the hierarchy where a "foo" was found
    within a directory named "sub". See
    the section on ANCHORING
    INCLUDE/EXCLUDE PATTERNS for a full
    discussion of how to specify a pattern
    that matches at the root of the
    transfer.
  • if the pattern ends with a / then it will only match a directory, not a
    regular file, symlink, or device.
  • rsync chooses between doing a simple string match and wildcard
    matching by checking if the pattern
    contains one of these three wildcard
    characters: '*', '?', and '[' .
  • a '*' matches any path component, but it stops at slashes.
  • use '**' to match anything, including slashes.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文