I'd like edit a file with sed on OS X. I'm using the following command:
sed 's/oldword/newword/' file.txt
The output is sent to the terminal. file.txt is not modified. The changes are saved to file2.txt with this command:
sed 's/oldword/newword/' file1.txt > file2.txt
However I don't want another file. I just want to edit file1.txt. How can I do this?
I've tried the -i flag. This results in the following error:
sed: 1: "file1.txt": invalid command code f
-i
flag?
You can use the -i
flag correctly by providing it with a suffix to add to the backed-up file. Extending your example:
sed -i.bu 's/oldword/newword/' file1.txt
Will give you two files: one with the name file1.txt
that contains the substitution, and one with the name file1.txt.bu
that has the original content.
Mildly dangerous
If you want to destructively overwrite the original file, use something like:
sed -i '' 's/oldword/newword/' file1.txt
^ note the space
Because of the way the line gets parsed, a space is required between the option flag and its argument because the argument is zero-length.
Other than possibly trashing your original, I’m not aware of any further dangers of tricking sed this way. It should be noted, however, that if this invocation of sed
is part of a script, The Unix Way™ would (IMHO) be to use sed
non-destructively, test that it exited cleanly, and only then remove the extraneous file.
I've similar problem with MacOS
sed -i '' 's/oldword/newword/' file1.txt
doesn't works, but
sed -i"any_symbol" 's/oldword/newword/' file1.txt
works well.
sed -i '' <file>
works but sed -i'' <file>
no longer works
The -i
flag probably doesn't work for you, because you followed an example for GNU sed while macOS uses BSD sed and they have a slightly different syntax.
All the other answers tell you how to correct the syntax to work with BSD sed. The alternative is to install GNU sed on your macOS with:
brew install gsed
and then use it instead of the sed
version shipped with macOS (note the g
prefix), e.g:
gsed -i 's/oldword/newword/' file1.txt
If you want GNU sed commands to be always portable to your macOS, you could prepend "gnubin" directory to your path, by adding something like this to your .bashrc
/.zshrc
file (run brew info gsed
to see what exactly you need to do):
export PATH="/usr/local/opt/gnu-sed/libexec/gnubin:$PATH"
and from then on the GNU sed becomes your default sed and you can simply run:
sed -i 's/oldword/newword/' file1.txt
sed -i -- "s/https/http/g" file.txt
--
seems to work, but in fact it creates a file.txt--
backup file, which must then be manually removed, so this solution is not better than the accepted one. And the --
is misleading, as if the option were acting like GNU tools which treat it differently.
You can use -i''
(--in-place
) for sed
as already suggested. See: The -i
in-place argument, however note that -i
option is non-standard FreeBSD extensions and may not be available on other operating systems. Secondly sed
is a Stream EDitor, not a file editor.
Alternative way is to use built-in substitution in Vim Ex mode, like:
$ ex +%s/foo/bar/g -scwq file.txt
and for multiple-files:
$ ex +'bufdo!%s/foo/bar/g' -scxa *.*
To edit all files recursively you can use **/*.*
if shell supports that (enable by shopt -s globstar
).
Another way is to use gawk
and its new "inplace" extension such as:
$ gawk -i inplace '{ gsub(/foo/, "bar") }; { print }' file1
This creates backup files. E.g. sed -i -e 's/hello/hello world/' testfile
for me, creates a backup file, testfile-e, in the same dir.
You can use:
sed -i -e 's/<string-to-find>/<string-to-replace>/' <your-file-path>
Example:
sed -i -e 's/Hello/Bye/' file.txt
This works flawless in Mac.
-i
requires an argument for macOS. Since you don't specify one, it uses -e
, which results in having a second file with -e
appended. -e
doesn't exist in macOS, it is -E
. So correct command for macOS is sed -i '' -E 's/Hello/Bye/' file.txt
Success story sharing
-i''
dangerous for any reason other than potentially messing up the original file (and having no back-up)?sed
man page if you run out of disk space on the device you could corrupt a file mid-stride and have a bad output result. If you are working under local source controlsed -i ""
without backups should be fine most of the time (or justgit init && git add -A . && git commit -m 'backup'
prior to running sed in-i
mode).-i''
is valid, but-i ''
is not.