glenatron
glenatron

Reputation: 11362

Ruby cannot open file ( Errno::ENOENT ) but the same path can be opened from IRB

I have a simple Ruby script that is building a list of files from an array of strings, so I have a method a bit like this:

  def initialize( rootpath, name )
    @content = ""
     intermission = ""
     if ( ! (rootpath[-1] == "/" || name[0] == "/" ))
       intermission="/"
       end

     @path= "#{rootpath}#{intermission}#{name}"
     print "Open JavascriptFile from #{@path}" 
     if (! File.exists? @path)
       print "File does not exist!" 
       end
     File.open( @path ).each do |line|
       @content << line
       end
     end

This is called along the lines of:

 files= ['alice.js', 'bob.js', 'claire.js', 'dave.js']
 basepath= "/home/glenatron/projects/myJSProject/"
 files.each do |filename|
    myLoader.new( basepath, filename )
    end

When I load in my classes from IRB and run this I get:

Open JavascriptFile from /home/glenatron/projects/myJSProject/alice.js
File does not exist!
Errno::ENOENT: No such file or directory - /home/glenatron/projects/myJSProject/alice.js

As I understand it, this means that the file does not exist.

However not only does the file definitely exist, in IRB I can paste the exact same path and see it's content - a simple File.open("/home/glenatron/projects/myJSProject/alice.js").each { | line | print line } reveals the complete content of the file. So why can I do this from a direct command line request and not from my Ruby class? Is it trying to read a local path instead of the full path I am passing it?

Upvotes: 3

Views: 1847

Answers (2)

falsetru
falsetru

Reputation: 369074

Guard the File.open .. lines with else block:

 if (! File.exists? @path)
   print "File does not exist!" 
 else # <---
   File.open( @path ).each do |line|
     @content << line
   end
 end  # <----

or return earlier in the if block:

 if (! File.exists? @path)
   print "File does not exist!" 
   return
 endif

Otherwise, the code always try to open the file, even if it does not exist.


Use File::join to join the path components:

File.join("/home/glenatron/projects/myJSProject/", "alice.js")
# => "/home/glenatron/projects/myJSProject/alice.js"
File.join("/home/glenatron/projects/myJSProject", "alice.js")
# => "/home/glenatron/projects/myJSProject/alice.js"

Edit to bring the solution ( in the comments ) into the answer: To find the exact path, use p @path - this revealed that the path that was trying to open looked like this when it failed: /home/glenatron/projects/myJSProject/alice.js\r which was causing the problem. A simple @path.strip! resolved it once this was clear.

Upvotes: 5

Michael Durrant
Michael Durrant

Reputation: 96484

From your code shown in the question, looks like an end instead of an else, e.g.

 if (! File.exists? @path)
   print "File does not exist!" 
   end   # <------------ This wasn't valid
 File.open( @path ).each do |line|
     @content << line
   end
 end

should be

 if (! File.exists? @path)
   print "File does not exist!" 
 else
   File.open( @path ).each do |line|
   @content << line
   end  # THIS end is valid as it ends a `.each` block
 end

Upvotes: 0

Related Questions