Skip to content
Home » The sed Command on macOS: What’s Different from Linux

The sed Command on macOS: What’s Different from Linux

macOS ships BSD sed at /usr/bin/sed, not the GNU version Linux uses. Most substitutions work the same, but a few differences turn a copied-from-Linux command into a cryptic error — and the -i flag is the one that bites hardest. Here’s exactly what differs, checked on macOS 26.5.2.

In-place editing: -i needs an argument

This is the single biggest difference. On Linux, sed -i 's/old/new/' file edits the file in place. On macOS, -i expects a backup suffix as its very next argument — so it swallows your script and falls over:

$ sed -i 's/foo/BAZ/' file.txt
sed: 1: "file.txt
": extra characters at the end of g command

That baffling message is BSD sed treating s/foo/BAZ/ as the backup suffix, then trying to run file.txt as the sed program. The fix is an explicit empty suffix, which means “edit in place, keep no backup”:

sed -i '' 's/foo/BAZ/' file.txt

The '' is the whole difference. It’s also why a script written for Linux can quietly misbehave on a Mac: without it, sed can end up creating a stray backup file named after your command instead of editing anything.

Editing with a backup: -i.bak

If you do want a backup, attach the suffix directly to -i with no space. This form works the same on macOS and Linux, which makes it the portable one to reach for:

$ sed -i.bak 's/foo/BAZ/' file.txt
$ ls file.txt*
file.txt  file.txt.bak

file.txt now holds the edit and file.txt.bak is the untouched original. The trap is only the space-separated empty suffix; a real suffix glued to -i is unambiguous either way.

Use -E for +, ?, and |

In its default basic-regex mode, BSD sed treats \+, \?, and \| literally rather than as quantifiers and alternation. A pattern that works on GNU sed matches nothing:

$ echo aaa | sed 's/a\+/X/'
aaa

Nothing changed, because a\+ looked for a literal a+. Turn on extended regular expressions with -E and use the bare metacharacters:

$ echo aaa | sed -E 's/a+/X/'
X

This is the same -E that the find command on macOS uses for extended regex — a consistent habit across the BSD tools.

GNU-only tricks that don’t work

A handful of GNU sed conveniences have no BSD equivalent. Case conversion in the replacement is the one people hit most:

$ echo hello | sed 's/.*/\U&/'
Uhello

\U isn’t a command in BSD sed — it comes out as a literal U. There’s no \U, \L, \u, or \l. If a script depends on them, the cleanest fix is to install GNU sed alongside the system one: Homebrew‘s gnu-sed formula provides it as gsed, so gsed 's/.*/\U&/' behaves exactly like it does on Linux, and /usr/bin/sed stays untouched.

The one to remember is -i '' — that’s the difference that turns a working Linux command into a puzzling error. After that: -i.bak for a backup, -E when you want +, ?, or |, and gsed for the GNU-only tricks. One thing that has caught up, worth noting since older guides still warn about it: \n in a replacement does produce a newline on current macOS sed, so that’s no longer a difference. All checked on macOS 26.5.2 against /usr/bin/sed.

Leave a Reply

Your email address will not be published. Required fields are marked *