在调试第三方Tcl脚本时,我遇到了一个非常奇怪的行为:当脚本通过gunzip解压缩现有文件时,Tcl'文件存在'拒绝结果文件存在,即使它是通过'ls可见的'从一个shell甚至通过Tcl'glob'。我能够在这个简短的(ish)脚本中复制行为:
#!/usr/bin/tclsh
proc assert {msg asserted} {
if {!$asserted} {
puts "Assertion failed: $msg"
exit 1
}
}
set script_path [info script]
set test_file [file join [file dirname $script_path] "test.tcl.gz"]
puts "The test file is '$test_file'"
assert "The test file does not exist" [file exists $test_file]
set this_dir [pwd]
set test_dir [file join $this_dir "test"]
if {![file exist $test_dir]} {
file mkdir $test_dir
}
puts "The test directory is '$test_dir'"
assert "'$test_dir' does not exist or is not a directory" [file isdirectory $test_dir]
file copy $test_file $test_dir
set working_file [file join $test_dir [file tail $test_file]]
assert "Failed to to copy the test file to '$working_file'" [file exists $working_file]
exec gunzip $working_file
puts "After decompression, $test_dir contains:"
foreach file [glob -dir $test_dir *] {
puts $file
}
set decompressed_file [file rootname $working_file]
assert "$decompressed_file does not exist" [file exists $decompressed_file]
我正在使用的测试文件只是脚本源的gzipped副本。它与脚本本身位于同一目录中,因为脚本需要并检查。这是我运行时得到的结果(tcl 8.5 / CentOS 6.5):
bash-4.1$ ./test.tcl
The test file is './test.tcl.gz'
The test directory is '/home/jbolling/tmp/test'
After decompression, /home/jbolling/tmp/test contains:
/home/jbolling/tmp/test/test.tcl
Assertion failed: /home/jbolling/tmp/test/test.tcl does not exist
任何人都可以解释这种行为吗?有没有办法说服'文件存在'来识别解压缩文件?
答案 0 :(得分:0)
file exists的手册说明了命令
如果文件名存在且当前用户已搜索,则返回1 通向它的目录的权限,否则为0。
显然该文件存在,因此我怀疑您运行该脚本的用户没有权限查看该文件。我必须承认,我不太确定是什么"搜索通往它的目录的权限"装置
我建议再次尝试使用位于公共可访问目录中的文件。
答案 1 :(得分:0)
向别人学习后#39;评论原始脚本为他们工作,发现一些对我有用的变体,并在Tcl源代码中探讨一些,我得出一个结论:曾经在对象上使用file exists
,它是不安全的如果目录的内容在调用之间可能已经改变(通常不能排除),则可以通过file rootname
在该对象上或从该对象派生的对象上再次使用它。
我还没有找到它在源代码中发生的地方,但是我的Tcl解释器显然正在缓存某个目录列表的结果,因为它不仅无法识别解压缩文件的创建,它也不能识别原件的删除(枪口也会执行)。另一方面,如果我使用文字字符串路径执行file exists
测试或使用与之前传递给file exists
的任何内容充分分离的Tcl对象,则结果与预期一致。如果我强制转换为字符串,例如替换
assert "$decompressed_file does not exist" [file exists $decompressed_file]
与
assert "$decompressed_file does not exist" [file exists [string trim $decompressed_file]]
显然,缓存行为是特定于实现的;我的实现是CentOS 6.5的Tcl 8.5.7,但我认为这种行为可能至少对于Tcl 8.5.7的Unix实现是一般的(这与macosx实现不同,即使OS X是Unix)。也许是gunzip正在做一些不寻常的事情,导致问题,因为我无法通过{{1}一个简单的mv命令复制它。
无论如何,尽管我还没有充分表明这个问题的特征,但我想我现在已经足够了解这个问题。感谢那些评论的人 - 你引导我朝着富有成效的方向前进。
答案 2 :(得分:0)
小问题,但看起来可能是错字......
if {![file exist $test_dir]} {
应该是:
if {![file exists $test_dir]} {