You’re not just replacing text—you’re performing bulk surgery on your codebase. Do it carefully.
You want to:
This is a common task in real projects: renaming variables, updating API endpoints, or fixing repeated mistakes.
Think of the pipeline like this:
[grep] → [xargs] → [sed/perl]
│ │ │
│ │ └── Modify file content
│ └────────────── Pass file list safely
└──────────────────────── Find matching files
Or more concretely:
Search → Select files → Apply transformation
Each tool does one job—and does it well.
grep -rl "abcabc" .
-r (or --recursive): Search recursively-l (or --files-with-matches): Print only filenames (not matching lines).: Start from current directory-r does NOT follow symbolic links-R if you want to follow themgrep -rlZ --exclude-dir=.git "abcabc" . \
| xargs -0 perl -pi -e 's/abcabc/cdecde/g'
-Z + -0)perl for reliable regex behavior.git directorygrep -rlZ-r: recursive search-l: output filenames only-Z (or --null): separate filenames with \0 (null character)Why this matters:
Normal output:
file one.txt
file two.txt
With -Z:
file one.txt\0file two.txt\0
This avoids breaking on spaces or weird filenames.
xargs -0Without this, filenames like:
my file.txt
would break your command.
perl -pi -e-p: loop over each line-i: edit files in place-e: execute codeReplacement:
s/abcabc/cdecde/g
's/abcabc/cdecde/g': Substitution command, replace all matches on each line
s/ = substituteabcabc = search pattern (treated as basic regex)cdecde = replacement stringg = global — replace all occurrences on each line (not just the first one).You can, but there are pitfalls.
sed -i 's/abcabc/cdecde/g'
sed -i '' 's/abcabc/cdecde/g'
That tiny difference ('') breaks scripts across platforms.
👉 This is why perl is often the safer default.
Dry-run / preview (before actual replacement):
# just list affected files
grep -rl "abcabc" .
Or inspect matches:
# show actual matching lines
grep -r "abcabc" .
grep -rlZ "abcabc" . \
| xargs -0 perl -pi.bak -e 's/abcabc/cdecde/g'
This creates a .bak backup of every modified file.
Always consider excluding:
.gitnode_modulesbuilddistExample:
grep -rlZ \
--exclude-dir=.git \
--exclude-dir=node_modules \
"abcabc" .
grep -rilZ "abcabc" . \
| xargs -0 perl -pi -e 's/abcabc/cdecde/gi'
perl -pi -e 's/\babcabc\b/cdecde/g'
(\b works reliably in Perl, not always in sed)
grep -rlZ --include="*.txt" --include="*.md" "abcabc" .
If you remember nothing else, remember this:
Search with
grep, pass safely withxargs -0, modify withperl.
That combination is:
grep -rlZ --exclude-dir=.git "abcabc" . \
| xargs -0 perl -pi -e 's/abcabc/cdecde/g'
Bulk replacement is powerful—but also dangerous.
A careless command can:
So treat it like any other engineering change:
Do that, and this becomes one of the most useful tools in your workflow.