Tcl'文件存在'错过了生成的文件

时间:2014-07-03 19:37:15

标签: tcl

在调试第三方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

任何人都可以解释这种行为吗?有没有办法说服'文件存在'来识别解压缩文件?

3 个答案:

答案 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]} {