---
title: 'sed command for Linux and Unix: Replace in-place'
teaser: 'Learn how to use the sed command to find and replace text in files in-place
  on Linux and Unix systems. This guide covers sed''s -i flag, backup options, and
  replacing across multiple files.

  '
tags: unix,linux,sed
author: Gabe Berke-Williams
published_on: 2014-01-15
---

Many people know how to use basic sed:

```sh
sed 's/hello/bonjour/' greetings.txt
echo "hi there" | sed 's/hi/hello/'
```

That'll cover 80% of your `sed` usage. This post is about the other 20%. Think
of it as a followup course after `sed` 101.

So you can change streams by piping output to `sed`. What if you want to change
the file in-place?

## Replacing in-place

`sed` ships with the `-i` flag. Let's consult `man sed`:

    -i extension
        Edit files in-place, saving backups with the specified extension.

Let's try it:

    $ ls
    greetings.txt
    $ cat greetings.txt
    hello
    hi there
    $ sed -i .bak 's/hello/bonjour/' greetings.txt
    $ ls
    greetings.txt
    greetings.txt.bak
    $ cat greetings.txt
    bonjour
    hi there
    $ cat greetings.txt.bak
    hello
    hi there

Note that the `-i` flag behaves differently between macOS (BSD `sed`) and Linux
(GNU `sed`). On macOS, `-i` requires an extension argument, even if it's an
empty string. On Linux, `-i` works without a separate argument. So:

- **macOS (BSD sed):** `sed -i .bak 's/hello/bonjour/' greetings.txt`
- **Linux (GNU sed):** `sed -i.bak 's/hello/bonjour/' greetings.txt`

So the original file contents are saved in a new file called `[file_name].bak`,
and the new, changed version is in the original `greetings.txt`. Now all we have
to do is:

```sh
rm greetings.txt.bak
```

And we've changed the file in-place. You are now the toast of the
office, sung of by bards.

## Replacing without a backup file

There's more in that `man` entry for `sed -i`:

    If a zero-length extension is given, no backup will be saved.  It is not
    recommended to give a zero-length extension when in-place editing files, as
    you risk corruption or partial content in situations where disk space is
    exhausted, etc.

Zero-length extension, eh? Let's use our original `greetings.txt` file before
we changed it:

    $ sed -i '' 's/hello/bonjour/' greetings.txt
    $ ls
    greetings.txt
    $ cat greetings.txt
    bonjour
    hi there
    $ cat greetings.txt.bak
    cat: greetings.txt.bak: No such file or directory

On macOS, `-i ''` tells `sed` to use a zero-length extension for the backup. On
Linux, you can simply use `-i` with no argument. A zero-length extension means
that the backup has the same name as the new file, so no new file is created. It
removes the need to run `rm` after doing an in-place replace.

I haven't run into any disk-space problems with `-i ''`. If you are worried
about the `man` page's warning, you can use the `-i .bak` technique I mention in
the previous section.

## Find and replace in multiple files

We like `sed` so much that we use it in [our `replace` script][replace]. It
works like this:

```sh
replace foo bar **/*.rb
```

The first argument is the string we're finding. The second is the string with
which we're replacing. The third is a pattern matching the list of files within
which we want to restrict our search.

Now that you're a `sed` master, you'll love reading `replace`'s [source
code][replace].

[replace]: https://github.com/thoughtbot/dotfiles/blob/main/bin/replace

## What's next

If you found this useful, you might also enjoy
the Grymoire [sed guide][sed-intro].
It's helpful when learning and as a reference.

Looking for a development team that sweats the details, from command-line
tooling to production infrastructure? [Let's talk][hire-us].

[sed-intro]: https://www.grymoire.com/unix/sed.html
[hire-us]: https://thoughtbot.com/hire-us
