File.exists? ignores file extension on windows?

I just wanted to check in with an issue I ran into last night.

I was trying to unpack a zip file using the following code which
appears to be the recommended way to extract using this library.

------------------------------8<------------------------------

Zip::ZipFile::open(zip_file) do |zf|
zf.each do |e|
fpath = File.join(dir, e.name)
FileUtils.mkdir_p(File.dirname(fpath))
zf.extract(e, fpath)
end
end

------------------------------>8------------------------------

Unfortunately for me, the archive I was extracting contained two
sibling files:

  1. bin/fcsh.exe
  2. bin/fcsh

One is obviously an executable and the other is an extension-free
shell script that points at it.

The Zip archive was raising a ZipDestinationFileExistsError every time
it encountered the second, extension-free file (I am attempting to
build cross-platform tools and was testing in Cygwin and DOS on
Windows XP).

As it turns out, the problem isn’t in the Zip library at all, but is
in the Windows version of Ruby File.exists?().

------------------------------8<------------------------------

I was able to faithfully reproduce the problem as follows:

FileUtils.touch(‘fcsh.exe’)
puts “exists?: #{File.exists?(‘fcsh’)}”

exists?: true

------------------------------>8------------------------------

Another interesting issue was that File.move also raises when you
attempt to move on top of what Ruby believes is an existing file,
while File.copy doesn’t seem to mind the ‘existing’ file.

It was also fascinating that even though File.exists? was returning
true, if I tried to do anything with that ‘existing’ file, I would get
FileNotFound exceptions.

As it turned out, this is the hack that I came up with at midnight
last night, is there a different/better workaround that other folks
know about?

------------------------------8<------------------------------

Zip::ZipFile::open(zip_file) do |zf|
zf.each do |e|
fpath = File.join(dir, e.name)
FileUtils.mkdir_p(File.dirname(fpath))
if(File.exists?(fpath) && !File.directory?(fpath))
hackpath = fpath + ‘hack’
zf.extract(e, hackpath)
File.copy(hackpath, fpath)
File.delete(hackpath)
else
zf.extract(e, fpath)
end
end
end

------------------------------>8------------------------------

I did some quick google searches for this problem and didn’t find any
mentions of it. Where do you folks search for answers to problems like
this?

I know that with Java, C#, JavaScript and ActionScript, I’m usually
able to just fire up google and put in the language and exception name

  • this usually brings me to someone with a similar problem. I haven’t
    found that to be the case with Ruby.

Are there any websites or blogs you have found (or written) that are
focused on developing cross platform ruby client code?

What resources do you keep at the top of your list for Ruby
development?

Thanks,

Luke B.
http://www.asserttrue.com

On Jun 12, 12:10 pm, Luke B. [email protected] wrote:

I just wanted to check in with an issue I ran into last night.

I was able to faithfully reproduce the problem as follows:

FileUtils.touch(‘fcsh.exe’)
puts “exists?: #{File.exists?(‘fcsh’)}”

exists?: true

I cannot duplicate this with Ruby 1.8.5 (one click) or 1.8.6 (VC++ 8)
on Windows XP SP2.

irb(main):002:0> VERSION
=> “1.8.6”
irb(main):003:0> FileUtils.touch(‘test.exe’)
=> [“test.exe”]
irb(main):004:0> File.exists?(‘test’)
=> false
irb(main):005:0> File.exists?(‘test.exe’)
=> true
irb(main):006:0> File.delete(‘test’)
Errno::ENOENT: No such file or directory - test
from (irb):6:in `delete’
from (irb):6
irb(main):007:0> File.delete(‘test.exe’)
=> 1

Regards,

Dan

Daniel B. wrote:

I cannot duplicate this with Ruby 1.8.5 (one click) or 1.8.6 (VC++ 8)
on Windows XP SP2.

I similarly cannot duplicate the problem with Ruby 1.8.6 (one click) on
Windows XP SP2. I get the exact same behavior shown in Daniel B.'s
post.

Luke B. wrote:

I was able to faithfully reproduce the problem as follows:

FileUtils.touch(‘fcsh.exe’)
puts “exists?: #{File.exists?(‘fcsh’)}”

exists?: true

Are you really sure ‘fcsh’ did not exist before the touch? There is
nothing in the above code snippet to demonstrate that is the case (like
a File.exists?(‘fcsh’) before the ‘touch’…)

As it turns out, I’m running ruby 1.8.5 and consistently reproduce the
issue in both irb and running a ruby file.

Here is the file that I’m running:

------------------------------8<------------------------------

require ‘fileutils’

base_name = ‘fcsh’
ext_name = ‘fcsh.exe’

if(File.exists?(ext_name))
File.delete(ext_name)
end

puts “Testing #{base_name}”
puts “exists a: #{File.exists?(base_name)}”
FileUtils.touch(ext_name)
puts “exists b: #{File.exists?(base_name)}”
puts “exists c: #{File.exists?(ext_name)}”

=> Testing fcsh
=> exists a: false
=> exists b: true
=> exists c: true

------------------------------>8------------------------------

I tried running it without using FileUtils, thinking maybe they had a
mixin that was causing problems, but no difference. I’m really glad I
had this old version because I’m planning on distributing this library
to random end users that may very well also have this older version of
Ruby!

Thanks,

Luke B.
http://www.asserttrue.com

Hi,

At Wed, 13 Jun 2007 03:15:03 +0900,
Luke B. wrote in [ruby-talk:255365]:

I was able to faithfully reproduce the problem as follows:

FileUtils.touch(‘fcsh.exe’)
puts “exists?: #{File.exists?(‘fcsh’)}”

exists?: true

You use cygwin.

$ rm -f fsch
$ touch fsch.exe
$ ./i386-cygwin/ruby.exe -e ‘p File.exist?(“fsch”)’
true
$ ./i386-mingw32/ruby.exe -e ‘p File.exist?(“fsch”)’
false
$ test -f fsch; echo $?
0
$ cmd /c “if exist fsch (echo exist) else (echo not exist)”
not exist

Unfortunately for me, the archive I was extracting contained two
sibling files:

  1. bin/fcsh.exe
  2. bin/fcsh

One is obviously an executable and the other is an extension-free
shell script that points at it.
[…]

As it turns out, the problem isn’t in the Zip library at all, but is
in the Windows version of Ruby File.exists?().

The problem is in Cygwin I believe. If you enter touch test.exe into
Cygwin and then enter ls -l test it will show the test.exe file.
This behavior seems to be confined to Cygwin as I don’t see the same
behavior under AIX.

This is correct, and the details can be found here:

http://www.cygwin.com/cygwin-ug-net/using-specialnames.html

(Scroll to the paragraph “The .exe extension”).

This is one of the compromises we have to live when bringing
Unix flavour to Windoze…

Ronald

Thanks for the responses!

The issue definitely makes more sense being a Cygwin problem and
constrained by .exe files.

Thanks,

Luke B.
http://www.asserttrue.com

Luke B. wrote:

FileUtils.mkdir_p(File.dirname(fpath))
  1. bin/fcsh
    in the Windows version of Ruby File.exists?().

The problem is in Cygwin I believe. If you enter touch test.exe into
Cygwin and then enter ls -l test it will show the test.exe file.
This behavior seems to be confined to Cygwin as I don’t see the same
behavior under AIX.

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs