Andrew Cheong
Andrew Cheong

Reputation: 30303

Can I find a filename from a filehandle in Tcl?

Similar to Can I find a filename from a filehandle in Perl? but in Tcl.

I plan to cache filename-filehandle associations anyway, so I'm asking purely out of curiosity--particularly of the "operating system wizardry" mentioned in the link. Is it possible in Tcl?

If it matters, I'm (forced into) using Tcl 8.0.5 on SunOS 5.10.

Upvotes: 5

Views: 2302

Answers (3)

smatalon
smatalon

Reputation: 1

You can run: exec lsof | grep -w [pid] | grep -w [fstat $file_handle ino]

Upvotes: 0

Donal Fellows
Donal Fellows

Reputation: 137787

With a version of Tcl that old, you really don't have all that many options. The simplest is to do a little bit of wrapping of open and close:

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
}

Then, you can get the filename for an open channel $ch by just reading $fileForChannel($ch).

Upvotes: 6

Hai Vu
Hai Vu

Reputation: 40783

I looked and did not find any way to get file name from handle, so I created my own solution. This solution uses the trace command to catch when the open command exits. At which time, both file names and handles are available, so I associate them to each other via the global fileNameFromHandle array.

# 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

Update

I don't have Tcl 8.0.5, to verify if this solution works. Please try it out and let me know. You can also trace the close command to remove the association.

Upvotes: 1

Related Questions