2

I have a program that tries to open a file:

Dir.chdir(File.dirname(__FILE__))
puts "Enter file name: ";
relPath = gets;
absPath = Dir.pwd << "/" << relPath;
if File.exist?(absPath) then
    puts "File exists";
    file = File.open(absPath, "r");
    other code...
else
    puts "File does not exist";
end

It always prints "File does not exist" even when the current directory exists and the file also exists. The file and script are in the same directory.

I am running it on Mac OS X Yosemite (10.10.3) and Ruby 2.2.0p0.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
flizana
  • 569
  • 6
  • 26

3 Answers3

0

That code has syntax error ("if" doesnt need "then"), and you dont have to put ";" after each line.

try

Dir.chdir(File.dirname(__FILE__))
puts "Enter file name: "
relPath = gets
absPath = "#{Dir.pwd}/#{relPath.chop}"
if File.exist?(absPath)
  puts "File exists"
  file = File.open(absPath, "r")
else
  puts "File does not exist"
end

remember that gets will add a new line character so you will need to do a chomp, and that way to concatenate string won't work on ruby.

Horacio
  • 2,865
  • 1
  • 14
  • 24
  • 1
    You could consider using `File.join Dir.pwd, relPath.chop` (or `File.expand_path(relPath.chomp)` ) to make it compatible on Windows as well as Unix. – Myst Oct 01 '15 at 00:52
0

I can't explain why (albeit I have strong belief that it's for some whitespace characters) but with this little contribution it works ok.

Dir.chdir(File.dirname(__FILE__))
print "Enter file name:";
relPath = gets.chomp; #intuitively used this, and it wroked fine
absPath = File.expand_path(relPath) #used builtin function expand_path instead of string concatenation
puts absPath
puts File.file?(absPath)
if File.exist?(absPath) then

    puts "File exists";
    puts File.ctime(absPath) #attempting a dummy operation :)

else
    puts "File does not exist";
end

runnning code

$ ls -a anal*
analyzer.rb
$ ruby -v
ruby 2.2.0p0 (2014-12-25 revision 49005) [x86_64-linux]
ziya@ziya:~/Desktop/code/ruby$ ruby fileexists.rb 
Enter file name:analyzer.rb
/home/ziya/Desktop/code/ruby/analyzer.rb #as a result of puts absPath
true #File.file?(absPath) => true
File exists
2015-06-11 12:48:31 +0500
marmeladze
  • 6,468
  • 3
  • 24
  • 45
  • 1
    the `gets` returns the `"\n"` (newline) character as part of the string. So, using `chomp` removed that extra character. I would also consider using `File.join` if the folder isn't relative to the `Dir.pwd`. – Myst Oct 01 '15 at 00:51
  • btw, `File.join` is more explicit than `File.expand_path`. the latter does its own magic but the first takes at least two arguments which describes the process very clearly. and i should have used it. – marmeladze Oct 01 '15 at 05:50
0

Your code is not idiomatic Ruby. I'd write it something like this untested code:

Dir.chdir(File.dirname(__FILE__))

puts 'Enter file name: '
rel_path = gets.chomp
abs_path = File.absolute_path(rel_path)

if File.exist?(abs_path)

  puts 'File exists'
  File.foreach(abs_path) do |line|
    # process the line
  end

else
  puts 'File does not exist'
end

While Ruby supports the use of ;, they're for use when we absolutely must provide multiple commands on one line. The ONLY time I can think of needing that is when using Ruby to execute single-line commands at the command-line. In normal scripts I've never needed ; between statements.

then is used with if when we're using a single line if expression, however, we have trailing if which removes the need for then. For instance, these accomplish the same thing but the second is idiomatic, shorter, less verbose and easier to read:

if true then a = 1 end
a = 1 if true

See "What is the difference between "if" statements with "then" at the end?" for more information.

Instead of relPath and absPath we use snake_case for variables, so use rel_path and abs_path. It_is_a_readability AndMaintenanceThing.

File.absolute_path(rel_path) is a good way to take the starting directory and return the absolute path given a relative directory.

File.foreach is a very fast way to read a file, faster than slurping it using something like File.read. It is also scalable whereas File.read is not.

Community
  • 1
  • 1
the Tin Man
  • 158,662
  • 42
  • 215
  • 303