在我的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 "
答案 0 :(得分:1)
要详细说明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
的agument列表(这是针对Tcl> = 8.5),如下所示:
set cmd [concat [list rsync -av] \
[glob -nocomplain /users/home/username/common/*]]
lappend cmd /tmp
catch {exec {*}$cmd} res
puts $res
更新:修复了示例,以便它确实有效。
答案 1 :(得分:1)
规范的写作方式是:
set srs "/users/home/username/common/*"
catch {exec rsync -av {*}[glob $src] /tmp} res
puts $res
这是因为默认情况下Tcl不会扩展glob元字符;这样更安全,更容易编写正确的代码(它是 hard 编写能够抵抗这方面问题的优秀shell代码),但它确实意味着你需要做一些额外的工作。额外的工作是:
$srs
命令询问glob
的全局扩展。这会返回一个列表。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或更高版本,请使用{*}
。真。
答案 2 :(得分:0)
那是因为tcl解释器没有扩展' *'像壳一样的符号。
例如:
$ tclsh
% cd /usr
% exec ls -d *
ls: *: No such file or directory
% exec sh -c "ls -d *"
X11R6
bin
docs
etc
...