From ac99f4926561355e4db4112066a96ef6d2211c2b Mon Sep 17 00:00:00 2001 From: Colin Patrick Mccabe Date: Mon, 30 Jul 2012 01:00:27 -0700 Subject: [PATCH] Add move_to_hierarchy.rb Signed-off-by: Colin McCabe --- move_to_hierarchy.rb | 115 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 115 insertions(+), 0 deletions(-) create mode 100755 move_to_hierarchy.rb diff --git a/move_to_hierarchy.rb b/move_to_hierarchy.rb new file mode 100755 index 0000000..5ae3b51 --- /dev/null +++ b/move_to_hierarchy.rb @@ -0,0 +1,115 @@ +#!/usr/bin/ruby -w + +# +# move_to_hierarchy.rb +# +# Moves all the files in a directory with the given file extension into a +# hierarchy. The maximum number of entries at each level is fixed. +# +# This is useful for arranging mp3s in a way that makes them easy to play on +# devices where large directories are impractical. +# +# Colin Mccabe +# + +require 'fileutils' +require 'optparse' +require 'ostruct' + +class MyOptions + DEFAULT_FILES_PER_LEVEL = 10 + + def self.parse(args) + opts = OpenStruct.new + opts.dry_run = false + opts.files_per_level = DEFAULT_FILES_PER_LEVEL + opts.extension = nil + $fu_args = { :verbose => true } + opts.preserve_names = false + + # Fill in $opts values + parser = OptionParser.new do |myparser| + myparser.banner = "Usage: #{ File.basename($0) } [opts]" + myparser.separator("Specific options:") + myparser.on("--files-per-level NFILES", "-L", + "Set the number of files per directory to use (default " + + DEFAULT_FILES_PER_LEVEL.to_s() + ").") do |d| + opts.files_per_level = d.to_i + end + myparser.on("--dry-run", "-d", + "Show what would be done, without doing it.") do |d| + $fu_args = { :verbose => true, :noop => true } + opts.dry_run = true + end + myparser.on("--file-extension EXTENSION", "-e", + "The file extension for the files to rename.") do |e| + opts.extension = e + end + end + + parser.parse!(args) + raise "invalid number of files per level: #{opts.files_per_level}" unless + opts.files_per_level > 1 + raise "must give an extension" unless opts.extension != nil + return opts + end +end + +def idx_to_path(idx) + num_digits = Math.log10($opts.files_per_level + 1).ceil() + path = "." + (0..idx.length - 2).each do |i| + v = idx[i] + path = path + "/" + (("%0" + num_digits.to_s + "d") % v) + end + return path +end + +def idx_increment(idx) + i = idx.length - 1 + while (idx[i] > $opts.files_per_level) + idx[i] = 1 + i = i - 1 + idx[i] = idx[i] + 1 + end +end + +# MAIN +begin + $opts = MyOptions.parse(ARGV) +rescue Exception => msg + $stderr.print("#{msg}.\nType --help to see usage information.\n") + exit 1 +end + +# get number of files +num_files = 0 +Dir.glob("*.#{$opts.extension}").sort.each do |f| + num_files = num_files + 1 +end +if (num_files == 0): + raise "No files found in the current working directory with extension " + + $opts.extension +end +num_levels = Math.log(num_files) / Math.log($opts.files_per_level) +num_levels = num_levels.ceil() +if ($fu_args[:verbose]) then + print "Number of files: " + num_files.to_s() + ". Number of levels: " + + num_levels.to_s() + "\n" +end + +idx = Array.new +(1..num_levels).each { |n| idx.push(1) } + +files_in_dir = 0 +Dir.glob("*.#{$opts.extension}").sort.each do |f| + path = idx_to_path(idx) + FileUtils.mkdir_p(path, $fu_args) + FileUtils.mv(f, path + "/" + f, $fu_args) + idx[idx.length - 1] = idx[idx.length - 1] + 1 + if (idx[idx.length - 1] > $opts.files_per_level) + idx_increment(idx) + end +end + +exit 0 -- 1.6.6.rc1.39.g9a42