Here's how to find and replace text across all files in a directory using sed:
find /path/to/dir -type f -exec sed -i 's/old_text/new_text/g' {} +
- find /path/to/dir -type f finds all regular files under the given directory recursively.
- -exec ... {} + runs the command on all matched files.
- sed -i edits files in place.
- 's/old_text/new_text/g' substitutes all occurrences of old_text with new_text. The g flag means global (all occurrences per line, not just the first).
You can narrow it down to specific file types:
find /path/to/dir -type f -name "*.py" -exec sed -i 's/old_text/new_text/g' {} +
Or exclude directories like .git:
find /path/to/dir -not -path '*/.git/*' -type f -exec sed -i 's/old_text/new_text/g' {} +
If your text contains slashes, you can use a different delimiter:
find /path/to/dir -type f -exec sed -i 's|/old/path|/new/path|g' {} +
To create a backup of each file before modifying it, pass an extension to -i:
find /path/to/dir -type f -exec sed -i.bak 's/old_text/new_text/g' {} +
This creates a .bak copy of every file before making changes, so you can revert if something goes wrong.
doing this all the time
If you do, then you should add this to your bashrc:
# find and replace across files recursively
gsed() {
if [ "$#" -lt 2 ]; then
echo "usage: gsed OLD NEW [PATH] [FILE_PATTERN]"
return 1
fi
local old="\$1"
local new="\$2"
local path="${3:-.}"
local pattern="${4:-*}"
find "$path" -type f -name "$pattern" -not -path '*/.git/*' -exec sed -i "s|$old|$new|g" {} +
}
Now you can just run:
gsed old_text new_text /path/to/dir "*.py"
Note that the pipe character | is used as the sed delimiter here so that slashes in your search or replacement text won't break anything.