pathname's each_entry

C

Claudio Greco

Hi all,

I noticed that the following code

require 'pathname'
p = Pathname.new('Test')
p.each_entry { | f | puts f.exist? }

does not work as I would expect.
I'm expecting that any returned object exists otherwise it wouldn't be
returned.
If 'Test' is a folder containing a single file, the iterator returns
three objects, and rightly so: . .. and the file, but only the first two
objects (directories) exist, not the file. Is this the expected
behavior?

Thanks in advance,

Claudio
 
D

Daniel Berger

Hi all,

I noticed that the following code

require 'pathname'
p =3D Pathname.new('Test')
p.each_entry { | f | puts f.exist? }

does not work as I would expect.
I'm expecting that any returned object exists otherwise it wouldn't be
returned.

Nope, Pathname.new doesn't enforce that a particular pathname exists
on your filesystem. That's up to you.

Regards,

Dan
 
C

Claudio Greco

Daniel said:
Nope, Pathname.new doesn't enforce that a particular pathname exists
on your filesystem. That's up to you.

Can you please clarify?
If I ask Pathname to return the entries that exist within a folder, then
by definition the objects returned must exist.

Claudio
 
D

Daniel Berger

Can you please clarify?
If I ask Pathname to return the entries that exist within a folder, then
by definition the objects returned must exist.

Hm, you're right. I was thinking each_entry simply yielded each piece
of the path.

I think you're getting false because Pathname#exist? isn't expanding
the path on the test. Trying using it in conjunction with
File.expand_path and see if that works.

Regards,

Dan
 
C

Claudio Greco

Daniel said:
Hm, you're right. I was thinking each_entry simply yielded each piece
of the path.
...
Trying using it in conjunction with
File.expand_path and see if that works.

I tried that before starting this thread

Claudio
 
S

Sean O'Halpin

I tried that before starting this thread

Claudio
--

Try this:

require 'pathname'
path = Pathname.new('Test')
path.each_entry { | f |
p [f, f.exist?, f.expand_path, path.join(f), path.join(f).exist?]
}
# >> [#<Pathname:.>, true, #<Pathname:/Users/ohalps01/scratch>,
#<Pathname:Test>, true]
# >> [#<Pathname:..>, true, #<Pathname:/Users/ohalps01>, #<Pathname:.>, true]
# >> [#<Pathname:hello>, false,
#<Pathname:/Users/ohalps01/scratch/hello>, #<Pathname:Test/hello>,
true]

It appears that each_entry yields just the basename, without any context.

Regards,
Sean
 
C

Claudio Greco

Sean said:
It appears that each_entry yields just the basename, without any
context.

You're right.

require 'pathname'
p = Pathname.new('C:/') # the same issue happens in Ubuntu
p.each_entry { | x | puts x.expand_path }

This code does not expand the path by prepending C:/, which I think
would be the wanted behavior: it prepends the current working directory.

In order to get my working directory I have to code as follows:

require 'pathname'
p = Pathname.new('C:/')
p.each_entry { | x | puts x.expand_path('C:/') }

So I've had a look at the source code for Pathname and each_entry, and
whenever each_entry iterates over the file system objects (located
within p in my case), the entry x is initialized simply with the name
(in this case the name of the file within C:/) and the link with C:/ is
lost forever, so while p knows about C:/, x does not.

The problem I think is that each_entry is implemented as:

def each_entry(&block)
Dir.foreach(@path) {|f| yield self.class.new(f) }
end

while I would prefer the following:

def each_entry(&block)
Dir.foreach(@path) {|f| yield self.class.new(@path+f) }
end



Thanks,

Claudio
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,575
Members
45,053
Latest member
billing-software

Latest Threads

Top