rsync 错误:使用包含“*”的源时特点

发布于 2024-12-24 22:30:40 字数 571 浏览 1 评论 0原文

在我的 TCL 脚本中,我使用 rsync 命令,不幸的是它拒绝同步包含“*”字符的路径。

代码示例:

 set srs "/users/home/username/common/*"
 catch {exec  rsync -av $src /tmp} res
 puts $res

输出:

 building file list ... done

 sent 29 bytes  received 20 bytes  98.00 bytes/sec
 total size is 0  speedup is 0.00
 rsync: link_stat "/users/home/username/common/*" failed: No such file or directory (2)
 rsync error: some files could not be transferred (code 23) at main.c(977) [sender=2.6.9]
    while executing
  "exec  rsync -rLptgov  $src /tmp "

In my TCL script I use rsync command and unfortunately it is refusing to sync path contain "*" character.

Code Example:

 set srs "/users/home/username/common/*"
 catch {exec  rsync -av $src /tmp} res
 puts $res

Output:

 building file list ... done

 sent 29 bytes  received 20 bytes  98.00 bytes/sec
 total size is 0  speedup is 0.00
 rsync: link_stat "/users/home/username/common/*" failed: No such file or directory (2)
 rsync error: some files could not be transferred (code 23) at main.c(977) [sender=2.6.9]
    while executing
  "exec  rsync -rLptgov  $src /tmp "

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

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

发布评论

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

评论(3

扭转时空 2024-12-31 22:30:40

规范的写法是:

set srs "/users/home/username/common/*"
catch {exec rsync -av {*}[glob $src] /tmp} res
puts $res

这是因为 Tcl 默认情况下不扩展 glob 元字符;这种方式更安全,并且更容易编写正确的代码(编写能够抵抗该领域问题的良好 shell 代码很难),但这确实意味着您需要做一些额外的工作。额外的工作是:

  1. 使用 glob 命令请求 $srs 的 glob 扩展。这会返回一个列表。
  2. 请求使用 {*} 伪运算符将列表扩展到 glob 之外(它不是一个运算符 — 从技术上来说它是一种语法 — 但它的工作原理是很多像一个)。

如果您使用的是 Tcl 8.4(或之前的版本!),那么您的做法有点不同:

set srs "/users/home/username/common/*"
catch {eval [list exec rsync -av] [glob $src] [list /tmp]} res
puts $res

好的,有时通常会通过省略 list 位来缩短(并且有有很多更晦涩的书写方式!)但这是一个坏习惯,因为在处理具有不“好”值的变量时(例如,路径名中带有空格),它可能会导致巨大的问题。如果您有 8.5 或更高版本,请使用 {*}。真的。

The canonical way of writing that is:

set srs "/users/home/username/common/*"
catch {exec rsync -av {*}[glob $src] /tmp} res
puts $res

This is because Tcl doesn't expand glob metacharacters by default; it's safer that way and easier to write correct code (it's hard to write good shell code that is resistant to problems in this area) but it does mean that you need to do a little extra work. The extra work is:

  1. Ask for glob expansion of $srs with the glob command. That returns a list.
  2. Ask for expansion of the list out of the glob by using the {*} pseudo-operator (it's not an operator — it's technically a kind of syntax — but it works a lot like one).

If you're using Tcl 8.4 (or before!) then you do it a bit different way:

set srs "/users/home/username/common/*"
catch {eval [list exec rsync -av] [glob $src] [list /tmp]} res
puts $res

OK, that's sometimes often shortened by leaving out the list bits (and there are many more obscure ways of writing it!) but that's a bad habit as it can cause huge problems when dealing with variables with values that aren't “nice”, e.g., with spaces in pathnames. If you have 8.5 or later, use {*}. Really.

白色秋天 2024-12-31 22:30:40

要详细说明 GrAnd 所说的内容,您必须显式构建源文件列表,可能使用 glob,所以你可以这样做

set cmd [concat [list exec rsync -av] \
                [glob -nocomplain /users/home/username/common/*]]
lappend cmd /tmp
catch {eval $cmd} res
puts $res

,或者使用 {*} 来扩展 exec 的参数列表(这适用于 Tcl >= 8.5) , 像这样:

set cmd [concat [list rsync -av] \
                [glob -nocomplain /users/home/username/common/*]]
lappend cmd /tmp
catch {exec {*}$cmd} res
puts $res

更新:修复了示例,使其真正有效。

To elaborate on what GrAnd said, you have to build the list of source files explicitly, probably using glob, so you'd do it like this

set cmd [concat [list exec rsync -av] \
                [glob -nocomplain /users/home/username/common/*]]
lappend cmd /tmp
catch {eval $cmd} res
puts $res

or, alternatively, use {*} to expand the agument list for exec (this is for Tcl >= 8.5), like this:

set cmd [concat [list rsync -av] \
                [glob -nocomplain /users/home/username/common/*]]
lappend cmd /tmp
catch {exec {*}$cmd} res
puts $res

Update: fixed example so that it really works.

土豪 2024-12-31 22:30:40

这是因为 tcl 解释器不会像 shell 那样扩展“*”符号。

例如:

$ tclsh
% cd /usr
% exec ls -d *
ls: *: No such file or directory
% exec sh -c "ls -d *"
X11R6
bin
docs
etc
...

That's because tcl interpreter does not expand the '*' symbol as shell does.

For example:

$ tclsh
% cd /usr
% exec ls -d *
ls: *: No such file or directory
% exec sh -c "ls -d *"
X11R6
bin
docs
etc
...
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文