Replacing strings in files based on certain search criteria is a common task. How I can...
- replace the string
foo
withbar
in all files in the current directory? - do the same thing recursively on subdirectories?
- replace only if filename matches some other string?
- replace only if the string is found in a given context?
- replace if string is on a given line number?
- replace multiple strings with the same replacement?
- replace multiple strings with different replacements?
This is an adaptation of the Unix & Linux question How can I replace a string in a file(s)? intended to serve as canon.
1. Replace the string
foo
withbar
in all files in the current directoryThis is the case when you know that the directory contains only regular files and that you want to process all non-hidden files. If this is not the case, use the solutions from point 2.
All solutions in this answer assume GNU
sed
.-i
If you're using FreeBSD or OS / X, substitute-i ''
. Also, note that use of the switch-i
has security implications for the filesystem and is not recommended in any script you intend to distribute in any way.( the solution in
perl
will fail for filenames ending in|
or space ).If you are using zsh:
(may fail if file list is too large, use
zargs
as possible workaround).Bash cannot directly check if the files are regular. A loop is needed (braces prevent define options globally):
Files are selected when they are actually files (
-f
) and can be written (-w
).2. Replace the string
foo
withbar
in all files in the current directory and its subdirectoriesThis is done on all regular files ( including hidden ones ) in this directory and its subdirectories.
3. Replace the string
foo
withbar
only if the filename matches some other string / has a certain extension / is of a certain type, etc.Not recursive, only files in this directory:
Recursive, regular files in this directory and its subdirectories:
If you're using Bash (the parentheses avoid setting the options globally):
If you use zsh:
--
it is used to tellsed
that no more options are going to be given on the command line. This is useful to protect against filenames starting with-
.If the file is of a certain type, for example, executable (read
man find
to see other options):zsh
:work in progress