While it is not that big a deal to cat a file before we send it to sed, fortunately, we don't really need to do that. The usage for sed is as follows: sed [OPTION] {script-only-if-no-other-script} [input-file]. As you can see at the end, there is an option for [input-file].
Let's take one of the previous examples, and remove the cat:
reader@ubuntu:~/scripts/chapter_10$ sed 's/wood/stone/g' search.txt
How much stone would a stonechuck chuck
if a stonechuck could chuck stone?
reader@ubuntu:~/scripts/chapter_10$ cat search.txt
How much wood would a woodchuck chuck
if a woodchuck could chuck wood?
As you can see, by using the optional [input-file] argument, sed processes all lines in that file according to the script. By default, sed prints everything it processes. In some cases, this causes lines to be printed twice, namely when using the print function of sed (which we will see in a bit).
Another very important thing that this example demonstrates: this syntax does not edit the original file; only what is printed out to STDOUT is changed. Sometimes, you will want to edit the file itself—for these scenarios, sed has the --in-place (-i) option.
Make sure you understand that this irreversibly changes the file on disk. And, as with most things in Linux, there is no such thing as an undo button or a recycle bin!
Let's see how we can use sed -i to persistently change a file (after we make a backup, of course):
reader@ubuntu:~/scripts/chapter_10$ cat search.txt
How much wood would a woodchuck chuck
if a woodchuck could chuck wood?
reader@ubuntu:~/scripts/chapter_10$ cp search.txt search.txt.bak
reader@ubuntu:~/scripts/chapter_10$ sed -i 's/wood/stone/g' search.txt
reader@ubuntu:~/scripts/chapter_10$ cat search.txt
How much stone would a stonechuck chuck
if a stonechuck could chuck stone?
This time, instead of printing the processed text onto your screen, sed quietly changed the file on disk. Because of the destructive nature of this, we created a backup beforehand. However, the --in-place option of sed can provide that functionality as well, by adding a file suffix:
reader@ubuntu:~/scripts/chapter_10$ ls
character-class.txt error.txt grep-file.txt grep-then-else.sh search.txt search.txt.bak
reader@ubuntu:~/scripts/chapter_10$ mv search.txt.bak search.txt
reader@ubuntu:~/scripts/chapter_10$ cat search.txt
How much wood would a woodchuck chuck
if a woodchuck could chuck wood?
reader@ubuntu:~/scripts/chapter_10$ sed -i'.bak' 's/wood/stone/g' search.txt
reader@ubuntu:~/scripts/chapter_10$ cat search.txt
How much stone would a stonechuck chuck
if a stonechuck could chuck stone?
reader@ubuntu:~/scripts/chapter_10$ cat search.txt.bak
How much wood would a woodchuck chuck
if a woodchuck could chuck wood?
sed is a bit stingy with the syntax. If you put a space between -i and '.bak', you will get weird errors (this normally works fine for commands whose options have arguments). In this case, because the script definition follows right after, sed is having trouble differentiating between what is the file suffix and script string.
Just remember that if you want to use this, you need to be careful about this syntax!