0

I have run into a problem in one of my Tcl scripts where I am uploading a file from a Windows computer to a Unix server. I would like to get just the original file name from the Windows file and save the new file with the same name. The problem is that [file tail windows_file_name] does not work, it returns the whole file name like "c:\temp\dog.jpg" instead of just "dog.jpg". File tail works correctly on a Unix file name "/usr/tmp/dog.jpg", so for some reason it is not detecting that the file is in Windows format. However Tcl on my Windows computer works correctly for either name format. I am using Tcl 8.4.18, so maybe it is too old? Is there another trick to get it to split correctly?

Thanks

Matt
  • 1,328
  • 1
  • 16
  • 28

2 Answers2

1

The problem here is that on Windows, both \ and / are valid path separators so long Windows API is concerned (even though only \ is deemed to be "official" on Windows). On the other hand, in POSIX, the only valid path separator is /, and the only two bytes which can't appear in a pathname component are / and \0 (a byte with value 0).

Hence, on a POSIX system, "C:\foo\bar.baz" is a perfectly valid short filename, and running

file normalize {C:\foo\bar.baz}

would yield /path/to/current/dir/C:\foo\bar.baz. By the same logic, [file tail $short_filename] is the same as $short_filename.

The solution is to either do what Glenn Jackman proposed or to somehow pass the short name from the browser via some other means (some JS bound to an appropriate file entry?). Also you could attempt to detect the user's OS from the User-Agent header.

To make Glenn's idea more agnostic to user's platform, you could go like this:

  1. Scan the file name for "/".
    • If none found, do set fname [string map {\\ /} $fname] then go to the next step.
  2. Use [file tail $fn] to extract the tail name.

It's not very bullet-proof, but supposedly better than nothing.

kostix
  • 51,517
  • 14
  • 93
  • 176
0

You could always do [lindex [split $windows_file_name \\] end]

glenn jackman
  • 238,783
  • 38
  • 220
  • 352