JnBrymn
JnBrymn

Reputation: 25353

Learning Ruby: return value

I'm learning Ruby, but I'm having trouble with the whole implicit return value thing. Someone please tell me why this returns an empty vector:

  3 def get_filenames(path)
  4   filenames = []
  5 
  6   if (path == ".") || (path == "..")
  7     []
  8   elsif File.directory? path
  9     Dir.entries(path).each do |sub_path|
 10       filenames += get_filenames(sub_path)
 11     end
 12   else #presumably it's a file
 13     [File.basename(path,".*")]
 14   end
 15 end

It should be returning an array of all file names (sans their extension) found when recursively searching from the argument path.

Assume that I call the function with "/tmp" and tmp contains 2 files: "A.txt" and "B.m" and then a directory which contains 1 file "C.exe". I want this function to return ["A","B","C"]

Upvotes: 0

Views: 2504

Answers (5)

zetetic
zetetic

Reputation: 47548

Your if statement has three paths; the first returns an empty array, and the last returns a single element wrapped in an array. So far so good.

But the middle path returns the value of Dir.entries, which itself returns all the entries for the folder identified by path. The each iterator produces the side effect of recursively calling get_filenames and appending them to the local variable filenames, but the return value of Dir.entries is not affected by this -- it still returns all the entries in the folder.

To get the result you want, just add filenames after the Dir.entries call.

Upvotes: 1

Andrei S
Andrei S

Reputation: 6516

first of all, Dir.entries does not get absolute paths, so when you try calling get_filenames(sub_path) you call for a relative filename path (and your function receives an absolute path)

use this:

def get_files(dir)
   files = []
   Find.find(dir) { |path| files << File.basename(path,".*") if FileTest.file?(path) }
   return files
end

Upvotes: 2

OscarRyz
OscarRyz

Reputation: 199215

This works on my machine as expected.

Try adding print statements in the argument and each one of the returned values to see what is actually happening in your case.

It is possible that your think you're passing one value when in fact you're passing another.

Upvotes: 0

Apoorv Saxena
Apoorv Saxena

Reputation: 4226

Here's a simple solution to your query... Find every file present in the current directory and sub-directories

{Find.find("", "#{path}") do |file|
 if File.file?(file)
   filenames << file.to_s
 end
end
}

Upvotes: 1

Michael
Michael

Reputation: 784

It is finding your if statement to be true, I believe, causing it to exit on the first pass through. What happens if you remove that portion of the logic (move elseif to if so you just have if and else?

Upvotes: 0

Related Questions