Forum: Ruby fugly hex

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.
Giles B. (Guest)
on 2007-07-06 06:45
(Received via mailing list)
Recently I got a hard drive back from a drive recovery place after it
had died a messy, violent, public death, like a Sopranos guest star.

I had to restore 65,536 directories.

Each directory contained some unknown (possibly zero) number of files.

The files were stored in directories with single-character names
running 0-f (hexadecimal).

My xargs fu was then too weak to handle this with a simple cp -r in
Unix. The argument list was too long. Additionally, the 65,536
directories did not yet exist in the new location.

The solution was pretty quick to implement:

hex = (0..9).to_a + %w{a b c d e f}

hex.each do |first|
  system "mkdir /new/#{first}"
  hex.each do |second|
    system "mkdir /new/#{first}/#{second}"
    hex.each do |third|
      system "mkdir /new/#{first}/#{second}/#{third}"
      hex.each do |fourth|
        system "mkdir /new/#{first}/#{second}/#{third}/#{fourth}"
        system "cp /original/#{first}/#{second}/#{third}/#{fourth}/*
/new/#{first}/#{second}/#{third}/#{fourth}/"
      end
    end
  end
end

The hardest part was being satisfied with the implementation, and
resisting the urge to improve it. There's a great deal of repetition
there.

How can I make it prettier?

--
Giles B.

Blog: http://gilesbowkett.blogspot.com
Portfolio: http://www.gilesgoatboy.org
Gregory B. (Guest)
on 2007-07-06 06:51
(Received via mailing list)
On 7/5/07, Giles B. <removed_email_address@domain.invalid> wrote:
> My xargs fu was then too weak to handle this with a simple cp -r in
>     system "mkdir /new/#{first}/#{second}"
>
> The hardest part was being satisfied with the implementation, and
> resisting the urge to improve it. There's a great deal of repetition
> there.

use fileutils instead of system, and move first_second_third_forth
into a var.  Then use mkdir_p instead of mkdir to avoid the first
three calls.

that's my 'quick glance' suggestion
Stefan R. (Guest)
on 2007-07-06 07:06
Sure
require 'fileutils' # as Gregory B. already stated
65536.times { |x|
  FileUtils.mkdir("new/%x/%x/%x/%x" % [x >> 12, x >> 8, x >> 4, x].map {
|x| x & 0xf })
}

Have fun
Stefan

Giles B. wrote:
> Recently I got a hard drive back from a drive recovery place after it
> had died a messy, violent, public death, like a Sopranos guest star.
>
> I had to restore 65,536 directories.
>
> Each directory contained some unknown (possibly zero) number of files.
>
> The files were stored in directories with single-character names
> running 0-f (hexadecimal).
>
> My xargs fu was then too weak to handle this with a simple cp -r in
> Unix. The argument list was too long. Additionally, the 65,536
> directories did not yet exist in the new location.
>
> The solution was pretty quick to implement:
>
> hex = (0..9).to_a + %w{a b c d e f}
>
> hex.each do |first|
>   system "mkdir /new/#{first}"
>   hex.each do |second|
>     system "mkdir /new/#{first}/#{second}"
>     hex.each do |third|
>       system "mkdir /new/#{first}/#{second}/#{third}"
>       hex.each do |fourth|
>         system "mkdir /new/#{first}/#{second}/#{third}/#{fourth}"
>         system "cp /original/#{first}/#{second}/#{third}/#{fourth}/*
> /new/#{first}/#{second}/#{third}/#{fourth}/"
>       end
>     end
>   end
> end
>
> The hardest part was being satisfied with the implementation, and
> resisting the urge to improve it. There's a great deal of repetition
> there.
>
> How can I make it prettier?
>
Giles B. (Guest)
on 2007-07-06 21:40
(Received via mailing list)
On 7/5/07, Stefan R. <removed_email_address@domain.invalid> wrote:
> Sure
> require 'fileutils' # as Gregory B. already stated
> 65536.times { |x|
>   FileUtils.mkdir("new/%x/%x/%x/%x" % [x >> 12, x >> 8, x >> 4, x].map {
> |x| x & 0xf })
> }

Excellent. I tested it in irb as a one-liner:

65_536.times {|x| puts("new/%x/%x/%x/%x" % [x >> 12, x >> 8, x >> 4,
x].map {|x| x & 0xf })}

But how does that work? Is there a way to make it more readable for
the programmer with no understanding of bit-shifting? (That would be
me, specifically.) Is there a way to make bit-shifting simple and
obvious?

Also, there's a showstopping flaw. It starts with trying to do:

FileUtils.mkdir "0/0/0/0"

But this throws an error in either Unix or irb, because you have to
mkdir 0 before you put the next 0 in it, and so on four levels down.
That's why I went with the nested each statements.

In words, what you need to do is, every time you get past the f at the
top of hexadecimal's 0-f, add a new level, and when you get to 4
levels, start copying files.

Is there a way to do it recursively, with an awareness of the level of
recursion?

--
Giles B.

Blog: http://gilesbowkett.blogspot.com
Portfolio: http://www.gilesgoatboy.org
Chris C. (Guest)
on 2007-09-26 01:10
(Received via mailing list)
On 7/6/07, Giles B. <removed_email_address@domain.invalid> wrote:

> Also, there's a showstopping flaw. It starts with trying to do:
>
> FileUtils.mkdir "0/0/0/0"
>
> But this throws an error in either Unix or irb, because you have to
> mkdir 0 before you put the next 0 in it, and so on four levels down.
> That's why I went with the nested each statements.
>
>

FileUtils.mkdir_p "0/0/0/0" # should do the trick
This topic is locked and can not be replied to.