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 Bowkett
Blog: http://gilesbowkett.blogspot.com
Portfolio: http://www.gilesgoatboy.org
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
···
On 7/5/07, Giles Bowkett <gilesb@gmail.com> 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.
Sure
require 'fileutils' # as Gregory Brown 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 Bowkett 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?
--
Posted via http://www.ruby-forum.com/\.
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?
···
On 7/5/07, Stefan Rusterholz <apeiros@gmx.net> wrote:
Sure
require 'fileutils' # as Gregory Brown already stated
65536.times { |x|
FileUtils.mkdir("new/%x/%x/%x/%x" % [x >> 12, x >> 8, x >> 4, x].map {
>x> x & 0xf })
}
--
Giles Bowkett
Blog: http://gilesbowkett.blogspot.com
Portfolio: http://www.gilesgoatboy.org
FileUtils.mkdir_p "0/0/0/0" # should do the trick
···
On 7/6/07, Giles Bowkett <gilesb@gmail.com> 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.
--
Chris Carter
concentrationstudios.com
brynmawrcs.com