Over SSH you often need to change a line in a configuration file, a .env or a wp-config.php, sometimes in many files at once. sed and perl can do it in one command, but a careless one-liner can also damage every file it touches. This guide shows how to choose the right tool, the safe way to run it, a cookbook of common edits, and when to reach for a structured tool or an editor instead.
Preview every change before you apply it (run without -i and pipe to diff), keep a backup (-i.bak), and limit the command to exactly the files you mean. Use sed for simple line edits, perl when you need lookarounds, multi-line matches or logic, and a structured tool such as jq, yq or crudini for JSON, YAML and INI files. Never pipe a file through a command and write it back to itself in the same pipeline; write to a temporary file and move it into place.
1. Safety rules for every edit
- Preview. Run the command without
-i, so it prints the result instead of saving it, and compare: `sed 's/OLD/NEW/g' app.confdiff -u app.conf -`. - Back up.Add a suffix to
-iso the original is kept:sed -i.bak 's/OLD/NEW/g' app.confleavesapp.conf.bakbehind. - Scope.Select files precisely with
find,git ls-filesor a named list, never a loose wildcard across a whole tree. - Check the result.Run the program's own config test (for example
nginx -torphp -l file.php) before you reload or restart anything. - Clean up.Delete the
.bakfiles once you're sure; a straywp-config.php.bakin a web folder can expose passwords.
sed 's/a/b/' file | tee file or cat file | sed 's/a/b/' > file can leave you with an empty file, because the shell or tee truncates the file before sed has finished reading it. Use -i, or write to a temporary file and move it: sed 's/a/b/' file > file.tmp && mv file.tmp file. The sponge command from moreutils also does this safely where it is installed.
2. sed or Perl?
| Need | sed | perl |
|---|---|---|
| Simple substitution, delete or insert a line | Ideal | Works, more typing |
| Groups and alternation | Use sed -E | Built in |
| Lookahead, lookbehind, non-greedy matches | Not supported | Built in |
| Changes that span several lines | Awkward | Easy with -0777 |
| Arithmetic or conditions on the match | No | Yes, with the /e flag |
| Same -i behaviour on Linux and macOS | No (see section 7) | Yes |
Rule of thumb: start with sed. Switch to perl as soon as the pattern needs a lookaround, a non-greedy match or more than one line. awk is the better choice for column-based data.
3. The cookbook
Each example shows the sed form and, where it helps, the perl form. Both keep a .bak backup.
Replace a path (use a different delimiter so slashes need no escaping):
sed -i.bak 's|/var/www/app|/srv/app|g' app.conf
perl -pi.bak -e 's|/var/www/app|/srv/app|g' app.confAdd a line after a match, and delete matching lines:
sed -i.bak '/^\[server\]/a max_connections = 200' app.ini
sed -i.bak '/^#\s*DEBUG/d' app.confComment out and uncomment a directive. Capture groups need -E in sed:
sed -i.bak -E 's/^(Listen 8080)/# \1/' app.conf
sed -i.bak -E 's/^#\s*(Listen 8080)/\1/' app.confSet a key to a value, whatever it was before:
sed -i.bak -E 's|^(\s*timeout\s*=\s*).*|\1"60s"|' app.conf
perl -pi.bak -e 's/^(\s*timeout\s*=\s*).*/${1}"60s"/' app.confChange a value only inside one section of an INI file:
sed -i.bak '/^\[server\]/,/^\[/ s/^port=.*/port=9090/' app.iniInsert a block after a heading (multi-line, so Perl):
perl -0777 -pi.bak -e 's/(\[logging\]\n)/$1level = "info"\nformat = "json"\n/' app.iniRemove Windows line endings before any other edit, since a hidden \r makes patterns fail to match:
sed -i.bak 's/\r$//' script.shChange one column with awk (awk has no in-place option, so write a new file):
awk -F'\t' -v OFS='\t' '{ $3 += 10 } 1' input.tsv > output.tsv4. Structured files: use a parser, not a regex
A regex doesn't understand nesting, quoting or escaping. For structured formats, a tool that parses the file is safer:
| Format | Tool | Example |
|---|---|---|
| JSON | jq | jq '.logging.level = "info"' config.json > config.json.tmp && mv config.json.tmp config.json |
| YAML | yq (v4) | yq -i '.server.port = 9090' config.yaml |
| INI | crudini | crudini --set app.ini server port 9090 |
| XML | xmlstarlet | xmlstarlet ed -L -u '/config/server/port' -v 9090 config.xml |
jq has no in-place option, so write to a temporary file and move it, as shown. These tools are packages you install on your own server; they are not always present on a shared or minimal system.
For PHP files such as wp-config.php, WordPress users can use WP-CLI, which edits the constants for you: wp config set WP_DEBUG false --raw.
5. Editors: nano, vim and scripted ex
For a single change you can see, an editor is often quicker and safer than a one-liner.
- nano is the easiest: open with
nano -l fileto show line numbers, save with Ctrl+O and exit with Ctrl+X. Ctrl+W searches. See Mastering nano for troubleshooting. - vim does repeatable edits well:
:%s/OLD/NEW/gcreplaces with a confirmation at each match. - ex, vim's line-editing mode, can run the same commands from a script:
ex -sc '%s/OLD/NEW/g|x' app.conf.
6. Many files at once
Select the files first, check the list, then edit:
# 1. See which files match
grep -rl --include='*.conf' 'OLD' config/
# 2. Edit exactly those, handling spaces in names safely
grep -rlZ --include='*.conf' 'OLD' config/ | xargs -0 -r sed -i.bak 's/OLD/NEW/g'In a Git repository, git ls-files -z '*.conf' | xargs -0 -r sed -i 's/OLD/NEW/g' touches only tracked files, and git diff shows exactly what changed. Commit before you start, and git checkout -- . undoes the edit completely.
For changes across many servers, a configuration tool such as Ansible (lineinfile, blockinfile, template) repeats the same edit reliably and records what it did.
7. Pitfalls
- Nothing changed. The pattern didn't match. Test it first with
grep -n 'pattern' file, and check for\rline endings. - Too much changed. Anchor with
^and$, or use word boundaries (\bin Perl and GNU sed). - macOS. BSD
sedneeds an argument after-i:sed -i '' 's/a/b/' filefor no backup. GNUsedon Linux accepts-ialone or-i.bak. - Symlinks.
sed -ireplaces a symlink with a regular file. Use--follow-symlinks(GNU sed) or edit the target path. - Ownership.
-iwrites a new file. Run as root, it can end up owned by root; check withls -lafterwards. - Speed and odd characters. Prefix with
LC_ALL=Cfor byte-wise matching on large or mixed-encoding files, and never run text tools on binary files.
8. Running this on Domain India
On shared hosting (cPanel, DirectAdmin or Webuzo), jailed SSH is available on every plan. It is off by default; ask support to enable it for your account, and log in with an SSH key. Inside the jail you edit files in your own account only, not server configuration. We checked the jail on our cPanel and DirectAdmin servers on 24 September 2026:
| Tool | cPanel jail | DirectAdmin jail |
|---|---|---|
| sed, perl, awk | Yes | Yes |
| nano | Yes | Yes |
| vim | Yes | No |
| diff | Yes | Yes |
| jq, yq | No | No |
| rsync | No | No |
To deploy many files, pack them into an archive, copy it with scp or SFTP, and unpack it with tar. Details are in Enabling and accessing jailed SSH.
On a Domain India VPS you have root access and can install any of the tools above. VPS plans are self-managed: you look after the system, updates and backups yourself. See VPS plans.
- 1 vCPU
- 2 GB DDR4 RAM
- 64 GB NVMe SSD Storage
- 2 TB Monthly Bandwidth
Prices on the cards exclude 18% GST.
How do I edit a file in place with sed and keep a backup?
Add a suffix to the -i option: sed -i.bak 's/old/new/g' file. The original is saved as file.bak and file holds the edited text.
When should I use Perl instead of sed?
When the pattern needs a lookahead or lookbehind, a non-greedy match, a change spanning several lines, or logic on the matched text. For simple line edits, sed is enough.
How can I preview a sed change without saving it?
Run the command without -i and pipe it to diff: sed 's/old/new/g' file | diff -u file -. Only the lines that would change are shown.
Why did my file become empty after a sed command?
The command probably wrote its output back to the same file in one pipeline, such as with tee or a redirect, which truncates the file before it is read. Use sed -i, or write to a temporary file and move it into place.
What is the safest way to edit a JSON or YAML file from the command line?
Use a parser rather than a regex: jq for JSON, writing to a temporary file and moving it, and yq for YAML. They understand the file's structure, so quoting and nesting stay correct.
Which editing tools are available in Domain India's jailed SSH?
On our cPanel and DirectAdmin servers the jail includes sed, perl, awk, nano and diff; vim is available on cPanel. jq, yq and rsync are not available. Jailed SSH is off by default; ask support to enable it.
Ready to work on your files over SSH? Read Enabling and accessing jailed SSH, learn more sed in Effective troubleshooting with sed, or open a support ticket to have SSH enabled on your account.
Jailed SSH is available on every shared hosting plan. Ask support to enable it, then log in with your SSH key.
Open a support ticket