0

I'm running a test script where one ruby script reads and executes additional ruby scripts from a 'scripts' folder.

Folder structure: RubyInception |_main.rb |_scripts |_1.rb |_2.rb 

Testing the filepaths like so:

irb(main):014:0> Dir.foreach('./scripts') {|x| puts File.absolute_path x} 

yielded the following results:

C:/.../Desktop/RubyInception C:/.../Desktop C:/.../Desktop/RubyInception/1.rb C:/.../Desktop/RubyInception/2.rb 

Why isn't it showing:

C:/.../Desktop/RubyInception/scripts/1.rb 

?

Environment:
Windows 7 Prof x64
ruby 1.9.3p448

SOLUTION:
What worked for me:

Dir["./scripts/*.rb"].each {|x| puts File.absolute_path x } 
1
  • If I do a Dir.chdir('./scripts') before executing this line, then I get the expected values, but why? Commented Jun 19, 2014 at 0:07

2 Answers 2

1

From documentation of Dir.foreach

Calls the block once for each entry in the named directory, passing the filename of each entry as a parameter to the block.

When you call

Dir.foreach('./scripts') 

it yields the following sequence to your block

. .. 1.rb 2.rb 

Note that no path information is contained in the result. Then in your block, you tried to resolve the absolute path of each filename. Since the filename doesn't have absolute path prefixed, the current working directory (CWD, or PWD) is used to resolve the absolute path of each entry. When CWD is RubyInception, you get:

File.absolute_path('.') => C:/.../Desktop/RubyInception File.absolute_path('..') => C:/.../Desktop File.absolute_path('1.rb') => C:/.../Desktop/RubyInception/1.rb File.absolute_path('2.rb') => C:/.../Desktop/RubyInception/2.rb 

When CWD is scripts, you get:

File.absolute_path('.') => C:/.../Desktop/RubyInception/scripts File.absolute_path('..') => C:/.../Desktop/RubyInception File.absolute_path('1.rb') => C:/.../Desktop/RubyInception/scripts/1.rb File.absolute_path('2.rb') => C:/.../Desktop/RubyInception/scripts/2.rb 

In summary, when you work with the file API of any programming language (is there any exception?), keep in mind the relative path starts from current working directory.

Sign up to request clarification or add additional context in comments.

Comments

0

See the documentation for explanation:

Relative paths are referenced from the current working directory of the process unless dir_string is given, in which case it will be used as the starting point.

So you could either use the dir_string parameter:

Dir.foreach('./scripts') {|x| puts File.absolute_path x, 'scripts'} 

Or Dir.glob:

Dir.glob('./scripts/*.rb') {|x| puts File.absolute_path x} 

4 Comments

The documentation is nonsensical--as is the result. Any method that produces an "absolute path" that doesn't exist is a bit puzzling.
@7stud You shouldn't downvote my answer just because you don't like the way Ruby works. Dir.foreach returns 1.rb, Dir.glob returns ./scripts/1.rb. Ruby has only these strings and the path to the current directory. This is the reason it can construct the absolute path correctly for Dir.glob, but not for Dir.foreach.
You shouldn't downvote my answer just because you don't like the way Ruby works That's not why I downvoted your answer. I downvoted your answer because you referenced nonsensical docs as the reason for the output the op is seeing. If you erase that nonsense and add your sensible comment to your answer, I will reverse my downvote...and I could even upvote your post.
@7stud What is nonsensical in the documentation? "Relative paths (1.rb) are referenced from the current working directory (C:/.../Desktop/RubyInception/)". The concatenation of these two strings is the wrong path (C:/.../Desktop/RubyInception/1.rb).

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.