[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Newb Wants to Better His File, Dir code

Robert Love

6/9/2007 2:31:00 AM

I've got code working to do what I want but I'm hoping there is a
better way. Mine seems clumsy.

My goal is to search over all files, identify all that are directories
and then do something to each directory. I don't need to go into
directories recursively yet.

The fact that Dir.foreach returns strings seems odd to me. All advice
appreciated.


#!/usr/local/bin/ruby

dpath = Dir.getwd

Dir.foreach(dpath) do
|x|
ddir = File.join(dpath,x)
if File.directory?(ddir) && x != "." && x != ".." then
puts %x{du -sh #{x}}
end
end


10 Answers

rio4ruby

6/9/2007 3:01:00 AM

0

On Jun 8, 7:31 pm, R. B. Love <rbl...@airmail.net> wrote:
> I've got code working to do what I want but I'm hoping there is a
> better way. Mine seems clumsy.
>
> My goal is to search over all files, identify all that are directories
> and then do something to each directory. I don't need to go into
> directories recursively yet.
>
> The fact that Dir.foreach returns strings seems odd to me. All advice
> appreciated.
>
> #!/usr/local/bin/ruby
>
> dpath = Dir.getwd
>
> Dir.foreach(dpath) do
> |x|
> ddir = File.join(dpath,x)
> if File.directory?(ddir) && x != "." && x != ".." then
> puts %x{du -sh #{x}}
> end
> end

One way simplify your handling of files and directories is to use Rio.
This will require you to install a module that is not a part of the
standard Ruby distribution. The easiest way to do this is:
gem install rio
(or on Unix or Linux: sudo gem install rio)

Then your code can be reduced to:

require 'rio'

rio.dirs do |x|
puts %x{du -sh #{x}}
end

Michael T. Richter

6/9/2007 3:31:00 AM

0

On Sat, 2007-09-06 at 11:35 +0900, R.B.Love wrote:

> I've got code working to do what I want but I'm hoping there is a
> better way. Mine seems clumsy.
>
> My goal is to search over all files, identify all that are directories
> and then do something to each directory. I don't need to go into
> directories recursively yet.
>
> The fact that Dir.foreach returns strings seems odd to me. All advice
> appreciated.
>
>
> #!/usr/local/bin/ruby
>
> dpath = Dir.getwd
>
> Dir.foreach(dpath) do
> |x|
> ddir = File.join(dpath,x)
> if File.directory?(ddir) && x != "." && x != ".." then
> puts %x{du -sh #{x}}
> end
> end


Try:


dirs = Dir.entries(".").reject{|e| /\.{1,2}/ =~ e}.find_all{|e|
File.directory? e}


At this point you have a list of directory names. You can do whatever
you like to that list using .each(), .inject(), .collect(), etc.

--
Michael T. Richter <ttmrichter@gmail.com> (GoogleTalk:
ttmrichter@gmail.com)
I can see computers everywhere - except in the productivity statistics!
(Robert Solow)

Dan Zwell

6/9/2007 3:42:00 AM

0

Michael T. Richter wrote:
> On Sat, 2007-09-06 at 11:35 +0900, R.B.Love wrote:
>
>> I've got code working to do what I want but I'm hoping there is a
>> better way. Mine seems clumsy.
>>
>> My goal is to search over all files, identify all that are directories
>> and then do something to each directory. I don't need to go into
>> directories recursively yet.
>>
>> The fact that Dir.foreach returns strings seems odd to me. All advice
>> appreciated.
>>
>>
>> #!/usr/local/bin/ruby
>>
>> dpath = Dir.getwd
>>
>> Dir.foreach(dpath) do
>> |x|
>> ddir = File.join(dpath,x)
>> if File.directory?(ddir) && x != "." && x != ".." then
>> puts %x{du -sh #{x}}
>> end
>> end
>
>
> Try:
>
>
> dirs = Dir.entries(".").reject{|e| /\.{1,2}/ =~ e}.find_all{|e|
> File.directory? e}
>
>
> At this point you have a list of directory names. You can do whatever
> you like to that list using .each(), .inject(), .collect(), etc.
>

The above has a small bug: it rejects all hidden directories. If you
want to block only ".." and ".", then change it to:

dirs = Dir.entries(".").reject{|e| /\.{1,2}$/ =~ e}.find_all{|e|
File.directory? e}

rio4ruby

6/9/2007 3:56:00 AM

0

On Jun 8, 8:42 pm, Dan Zwell <dzw...@gmail.com> wrote:
> Michael T. Richter wrote:
> > On Sat, 2007-09-06 at 11:35 +0900, R.B.Love wrote:
>
> >> I've got code working to do what I want but I'm hoping there is a
> >> better way. Mine seems clumsy.
>
> >> My goal is to search over all files, identify all that are directories
> >> and then do something to each directory. I don't need to go into
> >> directories recursively yet.
>
> >> The fact that Dir.foreach returns strings seems odd to me. All advice
> >> appreciated.
>
> >> #!/usr/local/bin/ruby
>
> >> dpath = Dir.getwd
>
> >> Dir.foreach(dpath) do
> >> |x|
> >> ddir = File.join(dpath,x)
> >> if File.directory?(ddir) && x != "." && x != ".." then
> >> puts %x{du -sh #{x}}
> >> end
> >> end
>
> > Try:
>
> > dirs = Dir.entries(".").reject{|e| /\.{1,2}/ =~ e}.find_all{|e|
> > File.directory? e}
>
> > At this point you have a list of directory names. You can do whatever
> > you like to that list using .each(), .inject(), .collect(), etc.
>
> The above has a small bug: it rejects all hidden directories. If you
> want to block only ".." and ".", then change it to:
>
> dirs = Dir.entries(".").reject{|e| /\.{1,2}$/ =~ e}.find_all{|e|
> File.directory? e}

This also has bug if you have a file name 'abc.'

Use rio.

Michael T. Richter

6/9/2007 4:14:00 AM

0

On Sat, 2007-09-06 at 12:42 +0900, Dan Zwell wrote:

> > dirs = Dir.entries(".").reject{|e| /\.{1,2}/ =~ e}.find_all{|e|
> > File.directory? e}



> The above has a small bug: it rejects all hidden directories. If you
> want to block only ".." and ".", then change it to:



> dirs = Dir.entries(".").reject{|e| /\.{1,2}$/ =~ e}.find_all{|e|
> File.directory? e}



Ah. That is true. I tested it in a directory that didn't have hidden
files or directories, so didn't note that.

--
Michael T. Richter <ttmrichter@gmail.com> (GoogleTalk:
ttmrichter@gmail.com)
Never, ever, ever let systems-level engineers do human interaction
design unless they have displayed a proven secondary talent in that
area. Their opinion of what represents good human-computer interaction
tends to be a bit off-track. (Bruce Tognazzini)

Michael T. Richter

6/9/2007 4:37:00 AM

0

On Sat, 2007-09-06 at 13:00 +0900, rio4ruby wrote:

> > dirs = Dir.entries(".").reject{|e| /\.{1,2}$/ =~ e}.find_all{|e|
> > File.directory? e}



> This also has bug if you have a file name 'abc.'


There's bugs in most (all?) off-the-cuff code put up in mailing lists to
illustrate a point. Yours (and the OP's) had the bug of not working on
directories with spaces in the name.


> Use rio.


http://snakeratpig.blogspot.com/2007/06/functional-poll...

--
Michael T. Richter <ttmrichter@gmail.com> (GoogleTalk:
ttmrichter@gmail.com)
A well-designed and humane interface does not need to be split into
beginner and expert subsystems. (Jef Raskin)

Florian Aßmann

6/9/2007 7:30:00 AM

0

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi rbLove,

another solution is to delete the array items beforehand:

class Dir
def self.dir_entries path, rejects = [ '.', '..' ]
( Dir.entries( path ) - rejects ).select { |entry|
File.directory? entry }
end
end

=begin
irb(main):021:0> Dir.chdir '/tmp'
=> 0
irb(main):022:0> Dir.dir_entries '.'
=> [".X11-unix", "501"]
irb(main):023:0> Dir.dir_entries '.', []
=> [".", "..", ".X11-unix", "501"]
irb(main):024:0>
=end

This is the code I'm still using...

Sincereley
Florian

Am 09.06.2007 um 06:36 schrieb Michael T. Richter:

> On Sat, 2007-09-06 at 13:00 +0900, rio4ruby wrote:
>> > dirs = Dir.entries(".").reject{|e| /\.{1,2}$/ =~ e}.find_all{|e|
>> > File.directory? e}
>> This also has bug if you have a file name 'abc.'
>
> There's bugs in most (all?) off-the-cuff code put up in mailing
> lists to illustrate a point. Yours (and the OP's) had the bug of
> not working on directories with spaces in the name.
>
>> Use rio.
>
> http://snakeratpig.blogspot.com/2007/06/functional-poll...
>
> --
> Michael T. Richter <ttmrichter@gmail.com> (GoogleTalk:
> ttmrichter@gmail.com)
> A well-designed and humane interface does not need to be split into
> beginner and expert subsystems. (Jef Raskin)

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (Darwin)

iD8DBQFGaldNl1R1ZNDW4WgRApPPAJ4/FVGxK7LXapjCAySUk7/FoyGP0QCfY6O2
a0a5NEcSS/etT88QZam2zHM=
=ImGP
-----END PGP SIGNATURE-----

skye.shaw

6/9/2007 5:40:00 PM

0

On Jun 8, 8:42 pm, Dan Zwell <dzw...@gmail.com> wrote:
> Michael T. Richter wrote:
> > On Sat, 2007-09-06 at 11:35 +0900, R.B.Love wrote:
>
> >> I've got code working to do what I want but I'm hoping there is a
> >> better way. Mine seems clumsy.
>
> >> My goal is to search over all files, identify all that are directories
> >> and then do something to each directory. I don't need to go into
> >> directories recursively yet.

<snip OP's code>

> > Try:
>
> > dirs = Dir.entries(".").reject{|e| /\.{1,2}/ =~ e}.find_all{|e|
> > File.directory? e}
>
> > At this point you have a list of directory names. You can do whatever
> > you like to that list using .each(), .inject(), .collect(), etc.
>
> The above has a small bug: it rejects all hidden directories. If you
> want to block only ".." and ".", then change it to:
>
> dirs = Dir.entries(".").reject{|e| /\.{1,2}$/ =~ e}.find_all{|e|
> File.directory? e}

If hidden directories are not important, maybe try:

[sshaw@localhost ~]$ ls -a
.. .emacs.d .ICEauthority .openoffice.org2.0
... .esd_auth images .recently-used
addr.pl .evolution java ruby

<snip long listing>

ruby -le'Dir["/home/sshaw/*/"].each { |d| print d }'
/home/sshaw/video/
/home/sshaw/me/
/home/sshaw/ruby/
/home/sshaw/java/
/home/sshaw/dos-mundos/
/home/sshaw/cti/
/home/sshaw/wb/
/home/sshaw/images/
/home/sshaw/music/
/home/sshaw/Desktop/
/home/sshaw/GDMX/
/home/sshaw/mysql/

Adrian Challinor

6/12/2007 6:44:00 AM

0

rio4ruby wrote:
> On Jun 8, 8:42 pm, Dan Zwell <dzw...@gmail.com> wrote:
>> Michael T. Richter wrote:
>>> On Sat, 2007-09-06 at 11:35 +0900, R.B.Love wrote:
>>>> I've got code working to do what I want but I'm hoping there is a
>>>> better way. Mine seems clumsy.
>>>> My goal is to search over all files, identify all that are directories
>>>> and then do something to each directory. I don't need to go into
>>>> directories recursively yet.
>>>> The fact that Dir.foreach returns strings seems odd to me. All advice
>>>> appreciated.
>>>> #!/usr/local/bin/ruby
>>>> dpath = Dir.getwd
>>>> Dir.foreach(dpath) do
>>>> |x|
>>>> ddir = File.join(dpath,x)
>>>> if File.directory?(ddir) && x != "." && x != ".." then
>>>> puts %x{du -sh #{x}}
>>>> end
>>>> end
>>> Try:
>>> dirs = Dir.entries(".").reject{|e| /\.{1,2}/ =~ e}.find_all{|e|
>>> File.directory? e}
>>> At this point you have a list of directory names. You can do whatever
>>> you like to that list using .each(), .inject(), .collect(), etc.
>> The above has a small bug: it rejects all hidden directories. If you
>> want to block only ".." and ".", then change it to:
>>
>> dirs = Dir.entries(".").reject{|e| /\.{1,2}$/ =~ e}.find_all{|e|
>> File.directory? e}
>
> This also has bug if you have a file name 'abc.'
>
> Use rio.
>

RIO is a great library. It is also a huge library to load for one simple
task. Though it has bugs in it, the author didn't claim that it was the
total solution nor that it didn't leave any holes - but the initial
comment from BB didn't ask for this - BB asked if the original code
worked or was "ugly".

Oh - and hats off to BB. A new person asking for advice on whether their
code is ugly is to be applauded.

What we would need to know is whether BB want to learn the best Ruby way
to do the directory search, or whether they want to do this as a
component in a much larger file processing application. If its the
former, then going with the pure Ruby code is good - and efficient. If
its the latter then RIO is an answer.

For me, the above solution would seem to be more in keeping with "The
Ruby Way".

Erik Hollensbe

6/12/2007 8:53:00 AM

0

On 2007-06-08 20:55:42 -0700, rio4ruby <Christopher.Kleckner@gmail.com> said:
>>> dirs = Dir.entries(".").reject{|e| /\.{1,2}/ =~ e}.find_all{|e|
>>> File.directory? e}
>>
>>> At this point you have a list of directory names. You can do whatever
>>> you like to that list using .each(), .inject(), .collect(), etc.
>>
>> The above has a small bug: it rejects all hidden directories. If you
>> want to block only ".." and ".", then change it to:
>>
>> dirs = Dir.entries(".").reject{|e| /\.{1,2}$/ =~ e}.find_all{|e|
>> File.directory? e}
>
> This also has bug if you have a file name 'abc.'
>
> Use rio.

Wouldn't changing the regex to read /^\.{1,2}$/ fix this problem?

Seems like a lot of unnecessary effort to complicate this code up with
an extra library to fix a regular expression.

-Erik