Skip to content

Instantly share code, notes, and snippets.

@moxley
Forked from sbecker/gfr.rb
Created August 30, 2012 21:43
Show Gist options
  • Save moxley/3541950 to your computer and use it in GitHub Desktop.
Save moxley/3541950 to your computer and use it in GitHub Desktop.
Global find and replace with optional confirm (with colored diff)
#! /usr/bin/env ruby
# Save this file to somewhere in your PATH, like ~/bin/gfr, and chmod it with: chmod u+x gfr
require 'rubygems'
require "highline/system_extensions"
require 'colorize'
require 'optparse'
require 'ostruct'
include HighLine::SystemExtensions
def ignore_patterns
@ignore_patterns ||= begin
ignore_file = "#{ENV['HOME']}/.gfr_ignore"
File.exists?(ignore_file) ? File.read(ignore_file).split(/\s+/) : []
end
end
def ignorable?(file_name)
ignore_patterns.each do |pattern|
return true if File.fnmatch(pattern, file_name)
end
false
end
def usage_and_quit
$stderr.puts banner
exit 2
end
def banner
"Usage: gfr [options] SEARCH REPLACE"
end
def parse_opts
options = { :confirm => false }
OptionParser.new do |opts|
opts.banner = banner
opts.on("-c", "--confirm", "Confirm each replacement") do |v|
options[:confirm] = true
end
end.parse!
[ARGV[0], ARGV[1], options]
end
def run
options = parse_opts
orig, new, opts = options
usage_and_quit if !(orig && new)
#file_names = Dir["**/*.*"]
file_names = `find . -type f`.split(/[\r\n]+/).reject{ |f| f == '.' || f == '..' }
file_names.each do |file_name|
text = File.read(file_name)
if text.index(orig)
p file_name
regexp = /(.*)(#{orig})(.*)/
new_text = text.gsub(regexp) do |line|
number = $`.split("\n").count + 1
puts "-#{number}: #{line}".red
puts "+#{number}: #{line}".gsub(orig, new).green
replacement = if opts[:confirm]
print "Replace '#{orig}' with '#{new}'? (y/n): "
input = get_character.chr
puts
input == 'y' ? new : orig
else
new
end
line.gsub(orig, replacement)
end
File.open(file_name, "w") do |file|
file.puts new_text
end
end
end
end
run
@moxley
Copy link
Author

moxley commented Aug 30, 2012

Enhancements:

  • Allows putting the -c argument anywhere in the command arguments
  • Allows specifying file patterns to ignore, using an ignore file at ~/.gfr_ignore
  • Search files in the current directory too (but calls out to the find command to do this)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment