Finding all empty directories in a subversion checkout

X-Cloudmark-Analysis: v=1.1 cv=FXfX1j538S0toKVv4AeTokQJ/Dr7x98IW2CddS+R9NE= c=1 sm=0 a=4Og3Em56ZtMA:10 a=IkcTkHD0fZMA:10 a=NEAV23lmAAAA:8 a=AkrA4ZvoYTkGoRutxRQA:9 a=_j8hiipnOi44SOWC491EbzjUegsA:4 a=QEXdDO2ut3YA:10 a=HpAAvcLHHh0Zw7uRqdWCyQ==:117
Precedence: bulk
Original-Lines: 52
List-Id: ruby-talk.ruby-lang.org
List-Software: fml [fml 4.0.3 release (20011202/4.0.3)]
List-Post: <mailto:ruby-talk@ruby-lang.org>
List-Owner: <mailto:ruby-talk-admin@ruby-lang.org>
List-Help: <mailto:ruby-talk-ctl@ruby-lang.org?body=help>
List-Unsubscribe: <mailto:ruby-talk-ctl@ruby-lang.org?body=unsubscribe>
Xref: news.gmane.org gmane.comp.lang.ruby.general:336318
Archived-At: <http://permalink.gmane.org/gmane.comp.lang.ruby.general/336318>

Hi,

I tried to write a script to find all empty directories in a subversion
checkout. In my view there were two main problems to solve:

1) empty directories also contain .svn control directories

2) directories containing only further empty directories should be
detected as such too.

I came up with https://gist.github.com/852051 and on my simple tests so
far it worked well. I'd like to get feedback on the code and how I used
certain idioms, or rather, miss-used certain idioms or areas where I can
improve it "the ruby way".

For example, I'm not really fond of the big case statement in the fourth
loop block:

    dirs_count[dir] =
        Dir.entries(dir).collect { |e|
            case e
            when '.svn'
                nil
            when '.'
                nil
            when '..'
                nil
            else
                e
            end
        }.compact.count

Seems pretty redundant to me, in other languages I'd have written e.g.

switch(e) {
  case '.svn':
  case '.':
  case '..':
    return nil;
  default:
    return e;
}

But I'm not sure how to apply that in ruby and I also think that these
could be improved anyway.

I'm sure a trained mind can spot other areas for improvement, I'm glad
for any suggestions!

thanks,
- Markus

case ... is the same as follows.
case e
  when '.svn', '.', '..'
    nil
  else
    e
end

Haruka YAGNI
hyagni@gmail.com

···

2011/3/3 Markus Fischer <markus@fischer.name>:

dirs_count[dir] =
Dir.entries(dir).collect { |e|
case e
when '.svn'
nil
when '.'
nil
when '..'
nil
else
e
end
}.compact.count

Instead of mapping values to nil and using compact, you can simply use
Enumerable#reject or #select. For this, though, since I think you can rely
on Dir.entries(dir).sort having "." and ".." as the first two entries, you
could get away with this:

Dir.entries(dir)[2..-1].reject { |e| e == ".svn" }

···

On Thu, Mar 3, 2011 at 12:15 AM, Markus Fischer <markus@fischer.name> wrote:

   dirs_count[dir] =
       Dir.entries(dir).collect { |e|
           case e
           when '.svn'
               nil
           when '.'
               nil
           when '..'
               nil
           else
               e
           end
       }.compact.count

And of course I forgot the .sort :slight_smile:

Dir.entries(dir).sort[2..-1].reject { |e| e == ".svn" }

···

On Thu, Mar 3, 2011 at 1:03 AM, Adam Prescott <mentionuse@gmail.com> wrote:

Dir.entries(dir)[2..-1].reject { |e| e == ".svn" }

2..-1 is not correct. It's mostly correct, but what if valid files with
name.ord < ".".ord (String#ord ruby19) exists?
p.e.

[sz@suessapfel:/tmp/foo]$ irb
irb:0> FileUtils.touch '-r'
=> ["-r"]
irb:0> Dir.entries(".").sort[-1..2]
=> [".."]
irb:0> ^D[sz@suessapfel:/tmp/foo]$ l
total 0
-rw------- 1 sz wheel 0B Mar 3 15:30 -r
drwx------ 3 sz wheel 102B Mar 3 15:30 ./
drwxrwxrwt@ 11 root wheel 374B Mar 3 15:30 ../

All the best, Sandor Szücs

···

On Mar 3, 2011, at 2:05 AM, Adam Prescott wrote:

On Thu, Mar 3, 2011 at 1:03 AM, Adam Prescott <mentionuse@gmail.com> wrote:

Dir.entries(dir)[2..-1].reject { |e| e == ".svn" }

And of course I forgot the .sort :slight_smile:

Dir.entries(dir).sort[2..-1].reject { |e| e == ".svn" }

--