In-place file editing
In the examples presented so far, the output from sed
was displayed on the terminal or redirected to another file. This chapter will discuss how to write back the changes to the input files using the -i
command line option. This option can be configured to make changes to the input files with or without creating a backup of original contents. When backups are needed, the original filename can get a prefix or a suffix or both. And the backups can be placed in the same directory or some other directory as needed.
The example_files directory has all the files used in the examples.
With backup
When an extension is provided as an argument to the -i
option, the original contents of the input file gets preserved as per the extension given. For example, if the input file is ip.txt
and -i.orig
is used, the backup file will be named as ip.txt.orig
.
$ cat colors.txt
deep blue
light orange
blue delight
# no output on terminal as -i option is used
# space is NOT allowed between -i and the extension
$ sed -i.bkp 's/blue/green/' colors.txt
# output from sed is written back to 'colors.txt'
$ cat colors.txt
deep green
light orange
green delight
# original file is preserved in 'colors.txt.bkp'
$ cat colors.txt.bkp
deep blue
light orange
blue delight
Without backup
Sometimes backups are not desirable. In such cases, you can use the -i
option without an argument. Be careful though, as changes made cannot be undone. It is recommended to test the command with sample inputs before applying the -i
option on the actual file. You could also use the option with backup, compare the differences with a diff
program and then delete the backup.
$ cat fruits.txt
banana
papaya
mango
$ sed -i 's/an/AN/g' fruits.txt
$ cat fruits.txt
bANANa
papaya
mANgo
Multiple files
Multiple input files are treated individually and the changes are written back to respective files.
$ cat f1.txt
have a nice day
bad morning
what a pleasant evening
$ cat f2.txt
worse than ever
too bad
$ sed -i.bkp 's/bad/good/' f1.txt f2.txt
$ ls f?.*
f1.txt f1.txt.bkp f2.txt f2.txt.bkp
$ cat f1.txt
have a nice day
good morning
what a pleasant evening
$ cat f2.txt
worse than ever
too good
Prefix backup name
A *
character in the argument to the -i
option is special. It will get replaced with the input filename. This is helpful if you need to use a prefix instead of a suffix for the backup filename. Or any other combination that may be needed.
$ ls *colors*
colors.txt colors.txt.bkp
# single quotes is used here as * is a special shell character
$ sed -i'bkp.*' 's/green/yellow/' colors.txt
$ ls *colors*
bkp.colors.txt colors.txt colors.txt.bkp
Place backups in a different directory
The *
trick can also be used to place the backups in another directory instead of the parent directory of input files. The backup directory should already exist for this to work.
$ mkdir backups
$ sed -i'backups/*' 's/good/nice/' f1.txt f2.txt
$ ls backups/
f1.txt f2.txt
Cheatsheet and summary
Note | Description |
---|---|
-i | after processing, write back changes to the source file(s) |
changes made cannot be undone, so use this option with caution | |
-i.bkp | in addition to in-place editing, preserve original contents to a file |
whose name is derived from the input filename and .bkp as a suffix | |
-i'bkp.*' | * here gets replaced with the input filename |
thus providing a way to add a prefix instead of a suffix | |
-i'backups/*' | this will place the backup copy in a different existing directory |
instead of source directory |
This chapter discussed about the -i
option which is useful when you need to edit a file in-place. This is particularly useful in automation scripts. But, do ensure that you have tested the sed
command before applying to actual files if you need to use this option without creating backups. In the next chapter, you'll learn filtering features of sed
and how that helps to apply commands to only certain input lines instead of all the lines.
Exercises
The exercises directory has all the files used in this section.
1) For the input file text.txt
, replace all occurrences of in
with an
and write back the changes to text.txt
itself. The original contents should get saved to text.txt.orig
$ cat text.txt
can ran want plant
tin fin fit mine line
$ sed ##### add your solution here
$ cat text.txt
can ran want plant
tan fan fit mane lane
$ cat text.txt.orig
can ran want plant
tin fin fit mine line
2) For the input file text.txt
, replace all occurrences of an
with in
and write back the changes to text.txt
itself. Do not create backups for this exercise. Note that you should have solved the previous exercise before starting this one.
$ cat text.txt
can ran want plant
tan fan fit mane lane
$ sed ##### add your solution here
$ cat text.txt
cin rin wint plint
tin fin fit mine line
$ diff text.txt text.txt.orig
1c1
< cin rin wint plint
---
> can ran want plant
3) For the input file copyright.txt
, replace copyright: 2018
with copyright: 2019
and write back the changes to copyright.txt
itself. The original contents should get saved to 2018_copyright.txt.bkp
$ cat copyright.txt
bla bla 2015 bla
blah 2018 blah
bla bla bla
copyright: 2018
$ sed ##### add your solution here
$ cat copyright.txt
bla bla 2015 bla
blah 2018 blah
bla bla bla
copyright: 2019
$ cat 2018_copyright.txt.bkp
bla bla 2015 bla
blah 2018 blah
bla bla bla
copyright: 2018
4) In the code sample shown below, two files are created by redirecting the output of the echo
command. Then a sed
command is used to edit b1.txt
in-place as well as create a backup named bkp.b1.txt
. Will the sed
command work as expected? If not, why?
$ echo '2 apples' > b1.txt
$ echo '5 bananas' > -ibkp.txt
$ sed -ibkp.* 's/2/two/' b1.txt
5) For the input file pets.txt
, remove the first occurrence of I like
from each line and write back the changes to pets.txt
itself. The original contents should get saved with the same filename inside the bkp
directory. Assume that you do not know whether bkp
exists or not in the current working directory.
$ cat pets.txt
I like cats
I like parrots
I like dogs
##### add your solution here
$ cat pets.txt
cats
parrots
dogs
$ cat bkp/pets.txt
I like cats
I like parrots
I like dogs