Reading contents of all files from a Directory

H

Hawksury Gear

Hello,
I am new to Ruby.

I am trying to "Read Content" of all the files from a Directory. So far
I can "Open" all files but this just shows the "names of all files" in
the directory and not the "file content".
My Program code is
arr= Dir.open("K:/test").entries
arr.each { |i| puts i }

I can open and read the content of an individual file using "File.open"
command but I don't know how to read the content of all the files in a
particular Directory.

It is may be very simple but I just can't find a way to do. Could you
please help?
Many Thanks,
:)
 
J

Jonathan Nielsen

I am trying to "Read Content" of all the files from a Directory. So far
I can "Open" all files but this just shows the "names of all files" in
the directory and not the "file content".
My Program code is
=C2=A0arr=3D Dir.open("K:/test").entries
=C2=A0arr.each { |i| puts i }

I can open and read the content of an individual file using "File.open"
command but I don't know how to read the content of all the files in a
particular Directory.

Hi,

You've got a good start there. As you have already figured out, the
arr.each iterator there gives you the name of each file. So, what you
would want to do to read the content of each file, is inside the each
iterator do a File.open(i), then do whatever you need with the
contents of the file.

arr =3D Dir.ope("K:/test").entires
arr.each do |file|
File.open(file) do |fd|
# do whatever you need with the file
end
end


-Jonathan Nielsen
 
J

Jonathan Nielsen

arr =3D Dir.open("K:/test").entries
arr.each do |file|
=C2=A0File.open(file) do |fd|
=C2=A0 =C2=A0# do whatever you need with the file
=C2=A0end
end

Wow, I typoed that bad, but I hope you get the idea. (corrected above.)
 
R

Robert Klemme

2010/3/21 Jonathan Nielsen said:
Wow, I typoed that bad, but I hope you get the idea. =A0(corrected above.=
)

If it is only for output purposes, we can actually do it in one line:

puts Dir["K:/test/*"].map {|f| File.read f}

Note: this is not necessarily efficient nor safe (just think of 3GB files..=
).

Kind regards

robert

--=20
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
 
J

jbw

Also might want to check if it is a file and skip directories:

puts Dir["/*"].map { |f| if(!File.directory?(f)) then File.read f end }

But yes this isn't necessarily efficient or safe.

2010/3/21 Jonathan Nielsen said:
Wow, I typoed that bad, but I hope you get the idea. =C2=A0(corrected ab=
ove.)

If it is only for output purposes, we can actually do it in one line:

puts Dir["K:/test/*"].map {|f| File.read f}

Note: this is not necessarily efficient nor safe (just think of 3GB files= ...).

Kind regards

robert



--=20
jbw
 
R

Robert Klemme

2010/3/22 jbw said:
Also might want to check if it is a file and skip directories:

puts Dir["/*"].map { |f| if(!File.directory?(f)) then File.read f end }

Good point!

Dir["dir/*"].each{|f| test ?f,f and puts File.read(f)}

:)

Cheers

robert
 
H

Hawksury Gear

If it is only for output purposes, we can actually do it in one line:
puts Dir["K:/test/*"].map {|f| File.read f}

Note: this is not necessarily efficient nor safe (just think of 3GB
files...).

Kind regards

robert

Many Thanks for replying robert, I am trying to print the contents of
each file
in the following way,It isn't giving me any error message but it is not
showing any output, Could you please help.

arr= Dir.open("K:/test").entries
arr.each do| file |
File.open("file","a+") do |fd|
fd.each {|line| print line}
end

Regards,
Gear
 
A

Aurélien AMILIN

[Note: parts of this message were removed to make it a legal post.]

First you should use file wich contain the filename of your file instead of
"file" which is a string
Then try to open your file with the r option not a+ (a+ means you place the
cursor at the end of the file to append some content while r is for reading
so the cursor is placed at the beginning of the file) so :

File.open(file,"r")
instead of :
File.open("file","a+")


2010/4/4 Hawksury Gear said:
If it is only for output purposes, we can actually do it in one line:

puts Dir["K:/test/*"].map {|f| File.read f}

Note: this is not necessarily efficient nor safe (just think of 3GB
files...).

Kind regards

robert

Many Thanks for replying robert, I am trying to print the contents of
each file
in the following way,It isn't giving me any error message but it is not
showing any output, Could you please help.

arr= Dir.open("K:/test").entries
arr.each do| file |
File.open("file","a+") do |fd|
fd.each {|line| print line}
end

Regards,
Gear
 
J

Jesús Gabriel y Galán

If it is only for output purposes, we can actually do it in one line:

puts Dir["K:/test/*"].map {|f| File.read f}

Note: this is not necessarily efficient nor safe (just think of 3GB
files...).

Kind regards

robert

Many Thanks for replying robert, I am trying to print the contents of
each file
in the following way,It isn't giving me any error message but it is not
showing any output, Could you please help.

=A0arr=3D Dir.open("K:/test").entries
=A0arr.each do| file |
=A0 =A0 =A0File.open("file","a+") do |fd|
=A0 =A0 =A0 =A0fd.each {|line| print line}
=A0 =A0 =A0 =A0end

You have two errors there. "file" is a literal string, not the
contents of the variable file. Use file without quotes.

The second:

http://ruby-doc.org/core/classes/IO.html

Take a look at the documentation of the open modes:

"a+" | Read-write, starts at end of file if file exists,
| otherwise creates a new file for reading and
| writing.


Starts at the end of the file, so there's nothing else to read...
You probably want this instead:

File.open(file, "r") do |file|
...
end

Jesus.
 
H

Hawksury Gear

Aurélien AMILIN said:
First you should use file wich contain the filename of your file instead
of
"file" which is a string
Then try to open your file with the r option not a+ (a+ means you place
the
cursor at the end of the file to append some content while r is for
reading
so the cursor is placed at the beginning of the file) so :

File.open(file,"r")
instead of :
File.open("file","a+")

Thanks for replying , if I do
File.open(file,"r")
## file without double quotes it gives an error message saying
"Permission Denied Errno::EACCESS"
But if I use the double qutoes i.e. File.Open("file","r") it doesn't
give any error message but also doesn't show any output.
Any idea why?
 
H

Hawksury Gear

Thanks for replying ,when I am doing

File.open(file,"r")

file without double quotes it gives an error message saying

"Permission Denied Errno::EACCESS"


Any idea why?
 
H

Hassan Schroeder

... it gives an error message saying

"Permission Denied Errno::EACCESS"

Any idea why?

Is there a reason you don't think it means exactly what it says?
 
H

Hawksury Gear

Hassan said:
Is there a reason you don't think it means exactly what it says?

No doubt, the error message is self explanatory.
But the actual files themselves in the directory allow Read and Write
operations so they are not protected against any Read/Write operations.I
have asked for the read-only permission="r" which in theory it should
grant.

Thanks,
Gear
 
H

Hassan Schroeder

No doubt, the error message is self explanatory.
But the actual files themselves in the directory =A0allow Read and Write
operations so they are not protected against any Read/Write operations.

But what about the permissions of the directory, and of the directory
which contains it, etc.?

Though I just realized looking at your original post that you're running
Windows, which means I have no idea, so I'll shut up now :)

Good luck,
--=20
Hassan Schroeder ------------------------ (e-mail address removed)
twitter: @hassan
 
H

Hawksury Gear

Your error is most likely caused by the fact that Dir#entries returns
file names only, i.e. without a path. You are trying to open different
files than you think (most likely in the current directory).

Kind regards
robert

Many Thanks for replying robert, It makes sense what you have said.
I think it would be a lot easier if I just explain my end goal. I think
my approach is probably wrong. This is what I want to achieve,

"Processing every single file that is in a particular directory"

My current approach is ,

1. Getting all files from a Directory using ab
=Dir.open("K:/test/").entries
2. Iterating over each file that is in the directory by doing;
ab.each do |f|
3. Applying "File.open" method (with required permission) to every
single 'file' by doing,
ab.each do |f|
File.Open(f,"w+") do |readfile|

4. Finally manipulating/processing each file line by line.

But what you said makes sense it looks like Dir.Open().entries doesn't
return a "file object" that can be manipulated it rather returns a
string (file name only).
Do you have any idea how this can be addressed?

Sorry to be a pain... new to Ruby!

Many Thanks,
 
R

Robert Klemme

No doubt, the error message is self explanatory.
But the actual files themselves in the directory allow Read and Write
operations so they are not protected against any Read/Write operations.I
have asked for the read-only permission="r" which in theory it should
grant.

Your error is most likely caused by the fact that Dir#entries returns
file names only, i.e. without a path. You are trying to open different
files than you think (most likely in the current directory).

Kind regards

robert
 
R

Robert Klemme

Many Thanks for replying robert, It makes sense what you have said.
I think it would be a lot easier if I just explain my end goal. I think
my approach is probably wrong. This is what I want to achieve,

"Processing every single file that is in a particular directory"

My current approach is ,

1. Getting all files from a Directory using ab
=Dir.open("K:/test/").entries

You should close the Dir object properly. You can either use the block
form of Dir.open or use the approach I have used below.
2. Iterating over each file that is in the directory by doing;
ab.each do |f|
3. Applying "File.open" method (with required permission) to every
single 'file' by doing,
ab.each do |f|
File.Open(f,"w+") do |readfile|

4. Finally manipulating/processing each file line by line.

But what you said makes sense it looks like Dir.Open().entries doesn't
return a "file object" that can be manipulated it rather returns a
string (file name only).
Do you have any idea how this can be addressed?

There are different ways. You can create proper file names with the
tools you have already:

dir = "K:/test"
Dir.entries(dir).each do |file|
path = File.join dir, file

if File.file? path
File.open path do |io|
io.each_line do |line|
...
end
end
end
end

Or you can use the elegant Pathname library:

require 'pathname'
dir = Pathname "K:/test"

dir.entries.each do |file|
if file.file?
file.each_line do |line|
...
end
end
end
Sorry to be a pain... new to Ruby!

No need to worry. We all start out as beginners at some point in time.

Kind regards

robert
 
R

Robert Klemme

Or you can use the elegant Pathname library:

Even better

require 'pathname'
dir = Pathname "K:/test"

dir.each_entry do |file|
if file.file?
file.each_line do |line|
...
end
end
end

Cheers

robert
 
H

Hawksury Gear

Even better
require 'pathname'
dir = Pathname "K:/test"

dir.each_entry do |file|
if file.file?
file.each_line do |line|
...
end
end
end

Cheers
robert

Many Thanks Robert, I did the following,

require 'pathname'
dir= Pathname "K:/test"
dir.each_entry do |file|
if file.file?
file.each {|line| print line} ## Checking if it can access a line in a
file
end
end

It isn't giving any error message which is great but also not Displaying
any Output.
Probably i am not using file.each{|line| print line} correctly.

Thanks,
Gear
 

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,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top