Skip to content

Instantly share code, notes, and snippets.

@seamusabshere
Created October 20, 2014 12:53
Show Gist options
  • Save seamusabshere/fb4d67618b25a2979d25 to your computer and use it in GitHub Desktop.
Save seamusabshere/fb4d67618b25a2979d25 to your computer and use it in GitHub Desktop.
global search and replace for filenames and file contents implemented in ruby with gsed
#!/usr/bin/env ruby
# USAGE gg "hello world" "hola mundo"
# * requirements: gem install posix-spawn, sudo port install coreutils (gsed)
# * changes file names and file contents (in the right order!)
# * limited regex support - it has to work with `system 'gsed', '--in-place', '-e', "s%#{search}%#{replace}%g", path`
require 'posix/spawn'
require 'fileutils'
force = ENV['FORCE'] == 'true'
search = ARGV[0]
replace = ARGV[1]
if ARGV.length > 2
content_paths = filename_paths = ARGV[2..-1]
unless content_paths.all? { |path| File.exist?(path) }
raise "#{path} doesn't exist"
end
else
child = POSIX::Spawn::Child.new 'ack', '--nofilter', '-l', '--print0', search
content_paths = child.out.split("\0")
filename_paths = Dir["**/*#{search}*"]
end
puts content_paths.join("\n")
puts
replace_content = force || begin
$stdout.write "Replace content? (y/n) "
(($stdin.gets.chomp) == 'y')
end
replace_in_filename = if force
true
elsif filename_paths.any?
puts filename_paths.join("\n")
puts
$stdout.write "Replace in filename? (y/n) "
(($stdin.gets.chomp) == 'y')
end
if replace_content
content_paths.each do |path|
puts "Replacing content in #{path}..."
system 'gsed', '--in-place', '-e', "s%#{search}%#{replace}%g", path
end
end
if replace_in_filename
filename_paths.each do |path|
puts "Replacing in filename #{path}..."
basename = File.basename path
dirname = File.dirname path
new_path = File.join(dirname, basename.sub(search, replace))
if path != new_path
FileUtils.mv path, new_path
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment