Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simplest way to properly search and replace source code

Every time this situation pops up, which is about once every few months, I end up spending way too long trying to figure out a bash script that does exactly what I want. I am pretty sure what I want is similar to what everyone else wants, but more often than not the available scripts online when I do a quick search are oversimplified and don't do these things (and my own bash scripting skills aren't good enough to figure it out):

  1. It needs to be recursive (traverse an entire folder tree)
  2. It must allow me to choose the type of file (e.g. "*.js") because sometimes the folder tree contains binaries and other file types that shouldn't be searched
  3. It should replace the text in-place, editing the existing files
  4. It shouldn't cause source control (git, svn) to think the file has been modified unless it actually has been modified (I don't know why but sed seems to do this)
  5. It should allow for regular expressions

What is the SIMPLEST way to accomplish this? I mean, I could write a script in python, it would only be a few lines, but I feel like this should be easy to accomplish in the shell.

like image 585
Fragsworth Avatar asked Jul 21 '26 00:07

Fragsworth


2 Answers

I typically do something like this:

find . -name '*.hpp' -o -name '*.cpp' | xargs grep -l StuffToEdit

I then see if I'm getting the files of interest. If I am, I add to the pipeline:

| xargs sed -i 's@StuffToEdit@NewStuffInstead@g'

And let 'er rip.

If sed is making your VCS think files are changed when they aren't, you should look at the diffs. Perhaps you have whitespace turned off in your diffs but that's what's changing (line endings or the like)?

I'm sure someone will come and point out that one or both of my uses of xargs up there are not necessary, but for one-off jobs, it doesn't matter. I prefer these multi-program pipelines for this sort of task anyway, since I can easily disable or swap out certain filters and check the results of the rest if the results are not correct at first.

like image 50
John Zwinck Avatar answered Jul 22 '26 16:07

John Zwinck


This should work as per your requirement:

find /path/to/dir/ -type f -name "*.txt" -exec sed -i 's/substitution/replacement/g' {} \;
|                 | |                     |    |                                   |     
 -----------------   ---------------------      -----------------------------------   
         |                     |                                 |                      
This will do the     This will allow you        This will do your substitution. -i       
search of files      to specify filename        option will do it inline. You can     
recursively for      You can also use           use -r option to use Extended Regex  
the supplied path.   -regex option for          as sed's native support is BRE.       
                      better search. -type
                     is to limit your search. 
                     i.e f for regular files,
                     d for directories, l for 
                     symbolic links etc
like image 28
jaypal singh Avatar answered Jul 22 '26 16:07

jaypal singh



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!