A port to change in an Nginx configuration, an IP address to update in ten files, a hostname to fix after a server rename: these operations come up constantly in Linux administration. Knowing how to do them fast, without mistakes and without opening a graphical editor, is one of an administrator's basic skills.
This guide covers the three main approaches: non-interactive replacement with sed (the most common in administration), interactive replacement in an editor (nano, vi, vim), and multi-file replacement by combining find and sed.
What you will learn
- Replace a word or a pattern in a file with
sed - Check a replacement before applying it
- Search and replace in nano, vi and vim
- Apply a replacement to several files at once
- Choose the right tool for the situation
Which tool for which situation?
Before going into each method, here is the quick decision rule:
| Situation | Recommended tool | Why |
|---|---|---|
| Quick replacement in a configuration file | sed | A single command, no editor to open |
| Replacement in a script or a pipeline | sed | Non-interactive, scriptable |
| Replacement with line-by-line visual check | vim (:s/.../gc) | Confirmation before each replacement |
| One-off edit of a simple file | nano | The most accessible for a beginner |
| Mass replacement in 10+ files | find + sed | Automated, no manual intervention |
| Large file whose context you need to understand | vim or vi | Built-in navigation and search |
Non-interactive replacement with sed
sed (stream editor) is the reference tool to change text on the command line. It reads a file line by line, applies a transformation and writes the result. You never leave your terminal.
Basic syntax
sed 's/old/new/' fileThis command replaces the first occurrence of old with new on each line, and prints the result on standard output. The original file is not modified.
To replace every occurrence on each line, add the g (global) flag:
sed 's/old/new/g' fileCheck before changing
Good practice is to always check the result before touching the file. sed prints the result by default without changing the file: take advantage of it.
-
See what will change:
Terminal window sed 's/8080/8443/g' /etc/nginx/sites-available/defaultThe whole file is shown with the replacements applied. Compare visually.
-
Target the lines involved:
Terminal window grep -n '8080' /etc/nginx/sites-available/defaultYou see the numbers of the lines containing the pattern, useful to check that nothing unwanted will be replaced.
-
Apply the change:
Terminal window sed -i 's/8080/8443/g' /etc/nginx/sites-available/defaultThe
-i(in-place) option modifies the file directly.
Concrete administration examples
Change a port:
sed -i 's/^Listen 80$/Listen 8080/' /etc/apache2/ports.confThe pattern is anchored: ^ for the start of the line, $ for the end. Without
these anchors, s/Listen 80/…/ would also change a Listen 8080 line. And the
target port must be free: Debian's ports.conf already declares Listen 443
for the SSL module, and changing Listen 80 into Listen 443 there makes
Apache reject the configuration (Cannot define multiple Listeners on the same IP:port). Always validate with sudo apache2ctl configtest before
reloading.
Replace an IP address:
sed -i 's/\b192\.168\.1\.10\b/192.168.1.20/g' /etc/hostsThe escaped dots (\.) only match a dot, and the \b boundaries
prevent touching a longer address. Without them, the line
192.168.1.100 db would become 192.168.1.200 db: it is the trap of the
address that contains another one.
Change a configuration setting:
sed -i 's/^#PermitRootLogin.*/PermitRootLogin no/' /etc/ssh/sshd_configThis last command uncomments and changes the line in a single operation. The ^# means "starts with #" and .* matches the rest of the line. On Debian and Ubuntu, sshd_config first includes the files in /etc/ssh/sshd_config.d/, and the first value read wins: check the value really applied with sudo sshd -T | grep -i permitrootlogin.
Alternative delimiter
When the text contains / (file paths, for example), use another delimiter to avoid unreadable escaping:
# Hard to readsed -i 's/\/usr\/local\/bin/\/opt\/bin/g' script.sh
# Readable: use | or # as the delimitersed -i 's|/usr/local/bin|/opt/bin|g' script.shRestrict to some lines
You can limit the replacement to a range of lines or to a pattern:
# Lines 10 to 20 onlysed -i '10,20s/old/new/g' file.conf
# Only the lines containing "server"sed -i '/server/s/8080/8443/g' nginx.confSearch and replace in an editor
Nano
In nano, the Ctrl+\ shortcut starts search/replace:
-
Open the file:
Terminal window nano /etc/hosts -
Press
Ctrl+\ -
Type the text to search, then Enter
-
Type the replacement text, then Enter
-
For each occurrence, nano asks you:
Y(replace),N(skip),A(replace all)
When to use nano: simple file, one-off change, you want to see what you are doing at each step. Full details in the nano guide.
Vi / Vim
In vi or vim, replacement is done from command mode:
:%s/old/new/g # Whole file, every occurrence:%s/old/new/gc # With confirmation for each occurrence:10,20s/old/new/g # Lines 10 to 20 onlyThe % means "the whole file". The c (confirm) flag shows you each occurrence and waits for your answer:
y, replacen, skipa, replace all (without asking any more)q, stop
To search without replacing, type /pattern in normal mode, then n for the next occurrence.
When to use vim: complex file, need for visual context, selective replacement with confirmation. Full details in the vi guide and the Vim guide.
Replace across several files
find + sed
To apply a replacement to every file in a directory:
find /etc/nginx/ -name '*.conf' -exec sed -i 's/8080/8443/g' {} +This command:
- finds all the
.conffiles in/etc/nginx/ - applies the
sedreplacement to each of them
grep + sed in a pipeline
A variant that only targets the files containing the pattern:
grep -rlZ 'old-hostname' /etc/ | xargs -0 sed -i 's/old-hostname/new-hostname/g'grep -rl lists the files containing the pattern (recursively, names only), and xargs passes each file to sed. The -Z / -0 pair separates the names with a null character: without it, a file named a b.conf is split into two names, and sed answers can't read.
Practical exercise
-
Create a test file:
Terminal window cat > /tmp/test-config.conf << 'EOF'server {listen 8080;server_name old-server.example.com;root /var/www/old-server;}EOF -
Check the content:
Terminal window cat /tmp/test-config.conf -
Replace the port with
sed(without changing the file):Terminal window sed 's/8080/443/' /tmp/test-config.confCheck that the
listenline shows443. -
Replace the hostname (changing the file):
Terminal window sed -i 's/old-server/new-server/g' /tmp/test-config.confcat /tmp/test-config.confBoth occurrences of
old-servermust have been replaced. -
Open it in vim and replace with confirmation:
Terminal window vim /tmp/test-config.confType
:%s/new-server/prod-server/gcthen approve each occurrence withy.
Troubleshooting
| Symptom | Likely cause | Solution |
|---|---|---|
sed replaces nothing | The pattern does not match exactly (case, spaces) | Check with grep first (grep -i ignores case), then add the I flag to sed: s/old/new/gI |
| Partial replacement (first occurrence only) | Missing g flag | Use s/old/new/g |
sed: -e expression #1, char X: unknown option to 's' | The text contains the / delimiter | Use an alternative delimiter: s|old|new|g |
File changed by mistake with -i | No prior backup | Restore from .bak if sed -i.bak was used, otherwise from a system backup |
Permission denied on a file in /etc/ | Insufficient permissions | Use sudo sed -i ... |
| Replacement in vim does not reach every line | Limited range (:s without %) | Use :%s/old/new/g for the whole file |
Special characters in the pattern (., *, [) | Interpreted as regular expressions | Escape them with \: sed 's/192\.168\.1\.10/192.168.1.20/g' |
Key points
sed -i 's/old/new/g' fileis the most used replacement command in Linux administration.- Always check before using
-i: runsedwithout-ior usegrep -nto see the lines involved. sed -i.bakautomatically creates a backup copy: prefer it on critical files.- Nano (
Ctrl+\) for one-off visual replacements. - Vim (
:%s/.../gc) for replacements with line-by-line confirmation. find+sedorgrep -rlZ+xargs -0 sedfor mass replacement across several files.- The dots (
.) in IP addresses are regex special characters: escape them with\.
Knowledge check
Check that the essentials of this guide stuck. The questions cover only what has just been explained here.
Knowledge check
Check what you have learned with this interactive quiz
How it works
- The timer starts when you click Start
- Multiple choice, true/false and short answer questions
- You can move between questions
- Detailed results are shown at the end
Starts the quiz and the timer
Review
(0/0)Score by domain
A domain groups several guides and gets several questions, so its score is more reliable than a per-topic score, which often rests on a single question.
Summary
Strengths
No topic passed at 80% on at least two questions yet.
Weak areas
No topic below the pass mark.
Recommended next
Hints before you try again?
Continue the course: Transform text with cut, tr and paste
A new full quiz with random questions
Work again only on the questions you missed