How to Use sed to Find and Replace Strings in Files

When working with text files, you will often need to find and replace strings of text in one or more files.
sed is a stream editor. It can perform basic text manipulation on files and input streams such as pipelines. With sed, you can search, find and replace, insert, and delete words and lines. It supports basic and extended regular expressions that allow you to match complex patterns.
This guide explains how to use sed to find and replace strings in files, covering the most common options, flags, and patterns.
To preview a find-and-replace operation before changing the file, use the s (substitute) command without -i:
sed 's/old-string/new-string/g' file.txtThis prints the edited content to the terminal without modifying file.txt. When the output looks correct, add -i.bak to edit the file in place and keep a backup, or use -i if you do not need one.
Find and Replace Strings with sed
There are several versions of sed, with some functional differences between them. macOS uses the BSD version, while most Linux distributions come with GNU sed pre-installed by default. The examples in this guide use GNU sed.
The general syntax for searching and replacing text with sed is:
sed -i 's/SEARCH_REGEX/REPLACEMENT/g' INPUTFILE-i- By default,sedwrites output to standard output. This option tellssedto edit the file in place. If an extension is supplied (for example-i.bak), a backup of the original file is created.s- The substitute command, the most commonly usedsedcommand./ / /- Delimiter character. It can be any character, but/is the most common choice.SEARCH_REGEX- A plain string or regular expression to search for.REPLACEMENT- The replacement string.g- Global replacement flag. By default,sedreplaces only the first match on each line. When this flag is set, all matches are replaced.INPUTFILE- The name of the file to operate on.
It is good practice to quote the expression so that shell meta-characters are not expanded.
For demonstration purposes, the examples below use the following file:
123 Foo foo foo
foo /bin/bash Ubuntu foobar 456If the g flag is omitted, only the first match on each line is replaced:
sed -i 's/foo/linux/' file.txt123 Foo linux foo
linux /bin/bash Ubuntu foobar 456With the global replacement flag, sed replaces all occurrences of the search pattern:
sed -i 's/foo/linux/g' file.txt123 Foo linux linux
linux /bin/bash Ubuntu linuxbar 456Notice that the substring foo inside foobar is also replaced. To match only whole words and avoid partial matches, use the word-boundary expression \b at both ends of the search string:
sed -i 's/\bfoo\b/linux/g' file.txt123 Foo linux linux
linux /bin/bash Ubuntu foobar 456To make the pattern case-insensitive, use the I flag. The following example uses both g and I:
sed -i 's/foo/linux/gI' file.txt123 linux linux linux
linux /bin/bash Ubuntu linuxbar 456If the search string contains the delimiter character (/), escape each slash with a backslash. For example, to replace /bin/bash with /usr/bin/zsh:
sed -i 's/\/bin\/bash/\/usr\/bin\/zsh/g' file.txtA cleaner approach is to use a different delimiter such as | or ::
sed -i 's|/bin/bash|/usr/bin/zsh|g' file.txt123 Foo foo foo
foo /usr/bin/zsh Ubuntu foobar 456sed also supports regular expressions. To replace all 3-digit numbers with the string number, run:
sed -i 's/\b[0-9]\{3\}\b/number/g' file.txtnumber Foo foo foo
foo /bin/bash Ubuntu foobar numberThe ampersand character & represents the matched pattern and can be used in the replacement string. For example, to wrap each 3-digit number in curly braces:
sed -i 's/\b[0-9]\{3\}\b/{&}/g' file.txt{123} Foo foo foo
foo /bin/bash Ubuntu foobar {456}It is always a good idea to create a backup before editing a file in place. To do this, provide a backup extension to the -i option. The following command edits file.txt and saves the original as file.txt.bak:
sed -i.bak 's/foo/linux/g' file.txtTo confirm the backup was created, list the files with ls
:
lsfile.txt file.txt.bakPreview Changes Without Modifying the File
Before running sed with the -i flag, it is good practice to preview the result first. Omitting -i sends the output to standard output without changing the file:
sed 's/foo/linux/g' file.txt123 Foo linux linux
linux /bin/bash Ubuntu linuxbar 456The original file remains unchanged. Once the output looks correct, add -i to apply the changes.
Replace Text on a Specific Line
To limit a substitution to a specific line number, place the line address before the s command:
sed '2s/foo/linux/' file.txt123 Foo foo foo
linux /bin/bash Ubuntu foobar 456To apply the replacement across a range of lines, use start,end before the s command:
sed '1,2s/foo/linux/g' file.txt123 Foo linux linux
linux /bin/bash Ubuntu linuxbar 456Replace the Nth Occurrence
By default, sed replaces the first match on each line. To replace only the Nth match, pass the occurrence number as a flag. For example, to replace only the second occurrence of foo per line:
sed 's/foo/linux/2' file.txt123 Foo foo linux
foo /bin/bash Ubuntu foobar 456To replace all occurrences starting from the Nth, combine the occurrence number with the g flag:
sed 's/foo/linux/2g' file.txt123 Foo foo linux linux
foo /bin/bash Ubuntu foobar 456Recursive Find and Replace
To recursively replace a string across all files in a directory, combine sed with find
or grep
.
The following command searches all files in the current working directory
and passes them to sed:
find . -type f -exec sed -i 's/foo/bar/g' {} +To handle filenames that contain spaces, use the -print0 option with xargs -0
:
find . -type f -print0 | xargs -0 sed -i 's/foo/bar/g'To limit the replacement to files with a specific extension:
find . -type f -name "*.md" -print0 | xargs -0 sed -i 's/foo/bar/g'To exclude hidden directories and files starting with a dot:
find . -type f -not -path '*/\.*' -print0 | xargs -0 sed -i 's/foo/bar/g'To replace only in files that actually contain the search string, use grep
to filter first:
grep -rlZ 'foo' . | xargs -0 sed -i.bak 's/foo/bar/g'Quick Reference
For a printable quick reference, see the Sed cheatsheet .
| Option / Flag | Description |
|---|---|
s/SEARCH/REPLACE/ | Replace first match per line |
s/SEARCH/REPLACE/g | Replace all matches (global) |
s/SEARCH/REPLACE/I | Case-insensitive match |
s/SEARCH/REPLACE/2 | Replace only the 2nd occurrence per line |
s/SEARCH/REPLACE/2g | Replace from the 2nd occurrence onwards |
\b | Word boundary, prevents partial word matches |
& | Reference to the matched pattern in replacement |
-i | Edit file in place |
-i.bak | Edit in place and save backup with .bak extension |
Ns/.../.../ | Limit substitution to line N |
N,Ms/.../.../ | Limit substitution to lines N through M |
Troubleshooting
sed: 1: "file.txt": undefined label on macOS
macOS ships with BSD sed, which requires an explicit extension or an empty string when using -i. On macOS, run sed -i '' 's/foo/bar/g' file.txt instead of sed -i 's/foo/bar/g' file.txt.
Pattern matches more than expected
Special regex characters such as ., *, [, and \ have special meaning in sed patterns. Escape them with a backslash if you want to match them literally. For example, to match a literal dot use \. instead of ..
No matches found despite the string being present
Check the delimiter character. If the search string contains /, either escape each slash with \ or switch to a different delimiter such as | or :. Also verify the file encoding; sed may not handle non-UTF-8 files as expected.
FAQ
How do I preview sed changes without modifying the file?
Run sed without the -i flag. The result is written to standard output and the original file is left unchanged.
Why does sed -i not work on macOS?
macOS uses BSD sed, which requires either a backup extension or an empty string after -i: sed -i '' 's/foo/bar/g' file.txt. On Linux, GNU sed accepts -i without an argument.
How do I replace a string that contains forward slashes?
Use a different delimiter character such as | or :. For example: sed 's|/bin/bash|/usr/bin/zsh|g' file.txt.
How do I replace text only on lines that match a pattern?
Use a regex address before the substitute command: sed '/pattern/s/foo/bar/g' file.txt. This applies the substitution only to lines containing pattern.
Conclusion
sed is a powerful tool for finding and replacing strings in files directly from the command line. Use the g flag for global replacement, \b for word boundaries, and -i.bak to keep a backup before modifying files in place. Always test your expression first by omitting -i to preview the output before committing changes.
Tags
Linuxize Weekly Newsletter
A quick weekly roundup of new tutorials, news, and tips.
About the authors

Dejan Panovski
Dejan Panovski is the founder of Linuxize, an RHCSA-certified Linux system administrator and DevOps engineer based in Skopje, Macedonia. Author of 800+ Linux tutorials with 20+ years of experience turning complex Linux tasks into clear, reliable guides.
View author page