I originally published this post on my blog. It's part of my personal C# Advent of Code.
These days I needed to rename all occurrences of one keyword with another in source files and file names. In one of my client's projects, I had to query one microservice to list a type of account to store it in an intermediate database. After a change in requirements, I had to query for another type of account and rename every place where I used the old one. This is what I learned.
My original solution was to use Visual Studio to replace "OldAccount" with "NewAccount" in all .cs
files in my solution. I used the "Replace in Files" menu by pressing: Ctrl + Shift + h.
With the "Replace in Files" menu, I covered file content. But I still had to change the filenames. For example, I needed to rename IOldAccountService.cs
to INewAccountService.cs
. I did it by hand. Luckily, I didn't have to replace many of them. There must be a better way!- I thought.
After renaming my files by hand, I thought I could have used the command line to replace both the content and file names. I use Git Bash anyways. Therefore I have access to most of Unix commands.
1. Replace 'old' with 'new' inside all .cs files
This is how to replace "Old" with "New" in all .cs
files, Source
grep -irl --include \*.cs "Old" | xargs sed -i 's/Old/New/g'
With the grep
command, we look for all .cs
files (--include \*.cs
) containing the "Old" keyword, no matter the case (-i
flag), inside all child folders (-r
), showing only the file path (-l
flag).
We could use the first command, before the pipe, to only list the .cs
files containing a keyword.
Then, with the sed
command, we replace the file content in place (-i
flag), changing all occurrences of "Old" with "New" (s/Old/New/g
). Notice the g
option in the replacement pattern.
This first command does what Visual Studio "Find in Files" does.
2. Rename 'old' with 'new' in filenames
Instead of renaming files by hand, this is how to replace "Old" with "New" in file names, Source
find . -path ./TestCoverageReport -prune -type f -o -name "*Old*" \
| sed 'p;s/Old/New/' \
| xargs -d '\n' -n 2 mv
This time, we're using the find
command to "find" all files (-type f
), with "Old" anywhere in their names (-name "*Old*"
), inside the current folder (.
), excluding the TestCoverageReport folder (-path ./TestCoverageReport -prune
).
Optionally, we can exclude multiple files by wrapping them inside parenthesis, like, Source
find . \( -path ./FolderToExclude -o -path ./AnotherFolderToExclude \) \
-prune -type f -o -name "*Old*"
Then, we feed the sed
command to generate new names replacing "Old" with "New." This time, we're using the p
option to print the "before" pattern. Up to this point, our command returns something like this,
./Some/Folder/AFileWithOld.cs
./Some/Folder/AFileWithNew.cs
...
With the last part, we split the sed
output by the newline character and passed groups of two filenames to the mv
command to finally rename the files.
Another alternative to sed followed by mv would be to use the rename command, like this,
find . -path ./TestCoverageReport -prune -type f -o -name "*Old*" \
| xargs rename 's/Old/New/g'
Voilà ! That's how to replace a keyword in the content and name of files. It took me some time to figure this out. But, we can rename files with two one-liners. It will save us time in the future. Kudos to StackOverflow.
Do you use the command line too? What Bash command or one-liners have saved your day? Feel free to leave a comment.
Stay tuned to my C# Advent of Code Posts.
Hey, there! I'm Cesar, a software engineer and lifelong learner. Visit my Gumroad page to download my ebooks and check my courses.
Happy coding!
Top comments (0)