5

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.

Community
  • 1
  • 1
Andrew Cheong
  • 29,362
  • 15
  • 90
  • 145

3 Answers3

6

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).

Donal Fellows
  • 133,037
  • 18
  • 149
  • 215
  • On Unix, you probably don't need to wrap `close` as channel names tend to be selected from a small set. Were you on Windows, it would be important to clean up as channel names there are more diverse. (This is due to the different nature of file descriptors on the two platforms.) – Donal Fellows Feb 28 '12 at 19:50
  • This is effectively what I have done--though I did not think of wrapping `close`. Thank you. – Andrew Cheong Mar 02 '12 at 14:43
1

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.

Hai Vu
  • 37,849
  • 11
  • 66
  • 93
  • Thanks for the suggestion Hai. Unfortunately, as @DonalFellows comments, command tracing is not available in Tcl 8.0.5. _"This command causes Tcl commands to be executed whenever certain operations are invoked. At present, only variable tracing is implemented. [...]"_ – Andrew Cheong Mar 02 '12 at 14:45
0

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

  • Could you please elaborate more your answer adding a little more description about the solution you provide? – abarisone Jun 23 '15 at 08:37