Safe Find & Replace: How Not to Break Binaries
Published on 2025-12-30
When working on real projects (CDN change, migration, refactor) you often need to bulk-replace one URL with another.
At first glance the task seems trivial: sed -i 's|old|new|g' **/* — and done.
In reality that approach is Russian roulette.
A careless replacement leads to:
- 💀 Corruption of binary files (images, pdf, archives);
- 📉 Garbage in git history (binaries marked as changed);
- 🚫 Inability to cleanly roll back if a backup wasn’t made.
In this note we’ll cover a production-grade algorithm: change only text, don’t touch binaries, make a targeted backup.
Input data
- Old URL:
https://static-old.example-cdn.net - New URL:
https://cdn-new.example-storage.net - Context: Project with mixed content (HTML, JS, YAML + PNG, JPG, WOFF2).
🛠 Steps
1. Preparation and search (Dry Run)
The key tool is grep -I (ignores binary files, even if bytes in them match the string).
First, just see what we’re going to change:
# Ищем рекурсивно, игнорируем бинарники, выводим список файлов
grep -rIl 'https://static-old.example-cdn.net' .
Important: make sure the list contains only text files (no images, fonts, etc.). If everything looks reasonable — proceed.
2. Create a “smart” backup
Don’t copy the whole project — that’s slow and takes space. Save only the files that contain the target string, preserving hierarchy and metadata.
SEARCH="https://static-old.example-cdn.net"
BACKUP_DIR="backup_before_replace"
mkdir -p "$BACKUP_DIR"
# Копируем только файлы с совпадением
find . -type f -print0 \
| xargs -0 grep -Il "$SEARCH" \
| xargs -I{} sh -c 'mkdir -p "$BACKUP_DIR/$(dirname "{}")" && cp -p "{}" "$BACKUP_DIR/{}"'
Now backup_before_replace contains an exact copy of only the files to be changed. Rollback is a simple copy back.
3. Perform the replacement (Safe Replace)
sed -i behaves differently on Linux (GNU) and macOS (BSD):
- Linux:
sed -i 's/old/new/g' - macOS:
sed -i '' 's/old/new/g'
To make the script work everywhere (locally, in CI, on Mac/Linux), use perl — it’s identical across *nix systems.
OLD="https://static-old.example-cdn.net"
NEW="https://cdn-new.example-storage.net"
find . -type f -not -path "./$BACKUP_DIR/*" -print0 \
| xargs -0 grep -Il "$OLD" \
| xargs -0 perl -pi -e "s|\Q$OLD\E|$NEW|g"
\Q and \E automatically escape all special characters in the URL (dots, slashes, dashes) — no need to escape manually.
4. Verify the result (Verification)
Make sure everything went well:
# Должно вернуть пустой вывод
grep -rIl "$OLD" . --exclude-dir="$BACKUP_DIR"
# Должно показать изменённые файлы (пример: первые 5)
grep -rIl "$NEW" . --exclude-dir="$BACKUP_DIR" | head -n 5
Additionally, you can run git status or git diff --stat to see the actual changes.
💡 Why this is correct
grep -I— reliable protection against damaging binaries.- Targeted backup — save only the delta, save space and time.
perlinstead ofsed— cross-platform stability (Linux, macOS, CI).- Variables and clear steps — the script is easy to read and adapt.
TL;DR — Ready-to-use snippet for “right now”
Paste into the terminal and replace your URLs:
SEARCH="https://static-old.example-cdn.net"
REPLACE="https://cdn-new.example-storage.net"
BACKUP="backup_$(date +%s)"
mkdir -p "$BACKUP"
# 1. Точечный бэкап только файлов с совпадением
find . -type f -print0 \
| xargs -0 grep -Il "$SEARCH" \
| xargs -I{} sh -c 'mkdir -p "$BACKUP/$(dirname "{}")" && cp -p "{}" "$BACKUP/{}"'
# 2. Безопасная замена (perl — работает на Linux и macOS)
find . -type f -not -path "./$BACKUP/*" -print0 \
| xargs -0 grep -Il "$SEARCH" \
| xargs -0 perl -pi -e "s|\Q$SEARCH\E|$REPLACE|g"
echo "Готово! Бэкап сохранён в папке $BACKUP"
echo "Откат (если нужно): cp -r $BACKUP/. ."
This approach is production-proven — safe, reliable, and universal. Good luck with your migrations! 🚀
Related reviews
Everything went well; the contractor responded quickly to questions and helped resolve the issue. Thanks!
visupSTUDIO · VPS setup, server setup
2025-12-16 · ⭐ 5/5
Everything went well, the contractor responded quickly to questions and helped resolve the issue. Thank you!
Everything was done promptly. We'll use them again. Highly recommend!
rotant · VPS setup, server setup
2025-12-10 · ⭐ 5/5
Everything was done promptly. We'll continue to use their services. I recommend!
Everything was done promptly. Mikhail is always available. We'll continue to contact him.
samstiray · VPS setup, server setup
2025-12-10 · ⭐ 5/5
Everything was done promptly. Mikhail is always available. We'll continue to reach out
Mikhail is a professional! He's shown this in practice more than once.
Vadim_U · VPS setup, server configuration
A settled customer2025-12-03 · ⭐ 5/5
Mikhail, a professional! Not the first time he's demonstrated this in practice.
Huge thanks to Mikhail — I contacted him about a very urgent server setup issue because I'm not strong in that area and needed to show the site to a client. Quick response, no-nonsense help, and very fast! Wishing you many orders and a better rating. Thank you so much!
Ekleo · VPS setup, server setup
A very powerful buyer2025-11-28 · ⭐ 5/5
Many thanks to Mikhail — I reached out to him with a very urgent issue regarding server configuration, since I'm not very skilled in this myself and needed to show the site to the client. Quick response, help without unnecessary words and very fast! I wish you many orders and a better rating! Thank you so much!
Thanks, that was quick and helpful.
Bodanov · VPS setup, server setup
Power buyer2025-11-28 · ⭐ 5/5
Thanks, that helped quickly.