Forum: Ruby Nuby - help with Ruby object references

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
A0c079a7c3c9b2cf0bffebd84dc578b0?d=identicon&s=25 unknown (Guest)
on 2006-02-24 01:36
(Received via mailing list)
I'm very new to Ruby (as in, just started yesterday). As a learning
exercise I decided to write a short program that would traverse a
directory tree and take note of all duplicate files in that tree.

I'm using a hash of arrays to track all references. The key is the
filename and I push the path as an array to store the value. If I run
across a filename for which a key already exists in the hash, I do a
deeper equality check to see if they are really the same file or if
they are different. The "deeper check" is comparing file sizes.

If they are the same, I push this new path into my array of arrays so
I can check against it if I find yet another file with that name. If
they're different, I push this new path onto a SECOND hash of arrays.

This is where I have trouble. As soon as I push any value into this
second hash, it takes on the identity of the first hash. I don't
understand why because I am not doing any explicit operation to make
hash1 = hash2. Maybe it's a side effect of some other operation.
Anyway, enough talk... the code is below.

I appreciate any and all insight.

cr

--- code here ---

#!/usr/bin/env ruby

require 'find'

h = Hash.new { |h,k| h[k] = [] }
duplicates = Hash.new { |h,k| h[k] = [] }

working_path = ARGV[0] || ENV["PWD"]

Find.find(working_path) do |path|
   # if it's a dir, skip to the next path
   if File.directory?(path)
     next
   end
   file = File.basename(path)

   # if this key doesn't exist in the hash, add it
   if h.has_key?(file) == false
     h[file].push([path])
   else  # key already exists in hash
     # add file size to hash unless it was already grabbed
     h[file].push([path])
     h[file].each do |subarray|
       subarray[1] = File.size(subarray[0]) unless subarray[1]
     end

     # now compare the current file's size to the prior check
     h[file].each do |subarray|
       puts "subarray[0] = #{subarray[0]} and path = #{path}"
       if subarray[0].eql?(path) == false && subarray[1] == File.size
(path)
         # add to dupe hash
         puts "DUPLICATE DUPLICATE DUPLICATE DUPLICATE"
         puts "DUP BEFORE h.id = #{h.object_id} and duplicates.id = #
{duplicates.object_id}"
         duplicates[file].push([path]) # at this point "h" and
"duplicates" refer to the same object!
         puts "DUP AFTER h.id = #{h.object_id} and duplicates.id = #
{duplicates.object_id}"
       end
     end
   end
end

puts "\n\nThe duplicates are..."
duplicates.each do |key, value|
   puts "key = #{key}"
   value.each do |a|
     print "#{a[0]} #{a[1]} "
   end
   print "\n"
end
Fe9b2d0628c0943af374b2fe5b320a82?d=identicon&s=25 Eero Saynatkari (rue)
on 2006-02-24 02:57
unknown wrote:
> <skip due to rforum/>
>
> I appreciate any and all insight.
>
> cr
>
> --- code here ---
>
> #!/usr/bin/env ruby
>
> require 'find'
>
> h = Hash.new { |h,k| h[k] = [] }
> duplicates = Hash.new { |h,k| h[k] = [] }

I am pretty sure this is where the problem is. Blocks
are closures so the 'h' in the second block refers to
the first Hash. Just change the first variable name
from 'h' to 'hash' in the whole file (it is a bit
clearer anyway) and you should be OK.

> <skip due to rforum/>


E
A0c079a7c3c9b2cf0bffebd84dc578b0?d=identicon&s=25 unknown (Guest)
on 2006-02-24 03:55
(Received via mailing list)
On Feb 23, 2006, at 7:58 PM, Eero Saynatkari wrote:

>>
>> require 'find'
>>
>> h = Hash.new { |h,k| h[k] = [] }
>> duplicates = Hash.new { |h,k| h[k] = [] }
>
> I am pretty sure this is where the problem is. Blocks
> are closures so the 'h' in the second block refers to
> the first Hash. Just change the first variable name
> from 'h' to 'hash' in the whole file (it is a bit
> clearer anyway) and you should be OK.

Okay, I did as you suggested and it works now. But...

I thought the scoping rules were different. I just checked pages 105
and 106 in the Pickaxe book to confirm the rules and they match up
with what you said. I'm clear on this now.

Thanks very much...

cr
This topic is locked and can not be replied to.