Skip to content

Instantly share code, notes, and snippets.

@sairam
Created December 26, 2019 18:03
Show Gist options
  • Save sairam/6a2211c7fda50877d94d2d4dddb04d77 to your computer and use it in GitHub Desktop.
Save sairam/6a2211c7fda50877d94d2d4dddb04d77 to your computer and use it in GitHub Desktop.
Deep Merge Directories on Linux and Mac
#!/usr/bin/env ruby
require 'fileutils'
require 'readline'
# Usage: (Interactive) ruby deep-merge-directories.rb dir1 dir2 dir3 new_dir
# Usage: (Non Interactive) CREATE_DIRECTORIES=yes MOVE_FILES=yes ruby deep-merge-directories.rb dir1 dir2 dir3 new_dir
# NOTE: empty directories will be created from source directories. files already present in new_dir may be overridden
# LICENSE: MIT
source_directories = ARGV[0..-2]
target_directory = ARGV[-1]
puts %{Source Directories: \n#{source_directories.join("\n")}}
puts %{Target Directory: #{target_directory}}
directories = source_directories.map do |source_directory|
Dir.glob("#{source_directory}/**/*").select{ |node| File.directory?(node) }.map{|dir| dir.sub(source_directory + "/", '') }
end.flatten.uniq
if directories.size > 0
puts %{New Directories to create: \n#{directories.join("\n")}}
print 'Press Enter to create new directories:'
input = ENV['CREATE_DIRECTORIES'] == 'yes' ? 'yes' : Readline.readline
puts "Aborted" && exit(1) if input.to_s.downcase[0] == 'n'
puts
FileUtils.mkdir_p directories.map{|directory| "#{target_directory}/#{directory}"}
end
target_files = {}
errors = []
files = source_directories.map do |source_directory|
Dir.glob("#{source_directory}/**/*").select{ |node| File.file?(node) }.map do |file|
new_file_location = "#{target_directory}#{file.sub(source_directory,'')}"
if target_files.key?(new_file_location)
errors << "Cannot move #{file} to #{new_file_location}. #{target_files[new_file_location]} already is assigned"
else
target_files[new_file_location] = file
end
end
end
if errors.size == 0
puts 'The following files will be renamed:'
target_files.each do |dest,src|
puts "#{src} => #{dest}"
end
print 'The above files will be renamed. Press Enter to continue, no to abort: '
input = ENV['MOVE_FILES'] == 'yes' ? 'yes' : Readline.readline
puts "Aborted" && exit(2) if input.to_s.downcase[0] == 'n'
puts
target_files.each do |dest,src|
FileUtils.move(src, dest)
end
puts "Files moved. Please delete source directories"
else
puts %{Errors: #{errors.join("\n")}}
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment