在Tcl中,我能否通过文件句柄找到文件名?

5
与Perl中的Can I find a filename from a filehandle in Perl?类似,这里是关于Tcl的。我计划无论如何都会缓存文件名-文件句柄的关联信息,所以我只是出于好奇而问——特别是在链接中提到的“操作系统魔法”。在Tcl中是否可能实现呢?如果有影响的话,我正在SunOS 5.10上使用Tcl 8.0.5。

8.0.5 真的非常古老。它已经超过十年没有得到支持了。 - Donal Fellows
3个回答

6

使用这么老的Tcl版本,你真的没有太多选择。最简单的方法是对openclose进行一些包装:

rename open _original_open
rename close _original_close

proc open {filename args} {
    global fileForChannel
    set channel [eval [list _original_open $filename] $args]
    set fileForChannel($channel) $filename
    return $channel
}
proc close {channel} {
    global fileForChannel
    catch {unset fileForChannel($channel)}
    _original_close $channel
}

接着,你可以通过读取$fileForChannel($ch)来获取打开通道$ch的文件名。


在Unix上,您可能不需要将close包装为通道名称,因为通常从一小组中选择通道名称。如果您在Windows上,则清理很重要,因为那里的通道名称更加多样化。(这是由于两个平台上文件描述符的不同性质所致。) - Donal Fellows
这实际上就是我所做的——尽管我没有想到包装close。谢谢。 - Andrew Cheong

1

我查找了一下,没有找到从句柄获取文件名的方法,所以我自己创建了一个解决方案。这个解决方案使用trace命令来捕获open命令退出时的情况。在此时,文件名和句柄都是可用的,因此我通过全局fileNameFromHandle数组将它们相互关联。

# This script demonstrate the use of the trace command to keep track
# the relationship between file handles and file names

# ======================================================================
# Setup trace to track file handle vs. file name
array set fileNameFromHandle {}
proc trace_proc {command code result op} {
    if {$code != 0} return; # Ignore failed calls

    set filename [lindex $command 1]; # command = {open filename mode}
    set filehandle $result
    set ::fileNameFromHandle($filehandle) $filename
}
proc getFileName {handle} { return $::fileNameFromHandle($handle) }
trace add execution open leave trace_proc

# ======================================================================
# Main
set handle1 [open file1.txt r]

# Do something with the files

# Need filename from handle?
puts "Handle: $handle1, filename: [getFileName $handle1]"

close $handle1

更新

我没有Tcl 8.0.5版本,无法验证这个解决方案是否有效。请尝试并告诉我结果。您也可以跟踪close命令以删除关联。


感谢您的建议,Hai。不幸的是,正如@DonalFellows所评论的那样,在Tcl 8.0.5中没有可用的命令跟踪功能。_"此命令会在调用某些操作时执行Tcl命令。目前,只实现了变量跟踪。[...]"_ - Andrew Cheong

0
你可以运行以下命令: exec lsof | grep -w [pid] | grep -w [fstat $file_handle ino]

您能否详细阐述一下您的答案,并对您提供的解决方案进行更多描述? - abarisone

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接