There is an easier way by using a simple script file:
# sudo chmod +x /bin/replace_string_files_present_dir
open the file in gedit or an editor of your choice, I use gedit here.
# sudo gedit /bin/replace_string_files_present_dir
Then in the editor paste the following in the file
#!/bin/bash
replace "oldstring" "newstring" -- *
replace "oldstring1" "newstring2" -- *
#add as many lines of replace as there are your strings to be replaced for
#example here i have two sets of strings to replace which are oldstring and
#oldstring1 so I use two replace lines.
Save the file, close gedit, then exit your terminal or just close it and then start it to be able load the new script you added.
Navigate to the directory where you have multiple files you want to edit. Then run:
#replace_string_files_present_dir
Press enter and this will automatically replace the oldstring and oldstring1 in all the files that contain them with the correct newstring and newstring1 respectively.
It will skip all the directories and files that don’t contain the old strings.
This might help in eliminating the tedious work of typing in case you have multiple directories with files that need string replacement. All you have to do is navigate to each of those directories, then run:
#replace_string_files_present_dir
All you have to do is to ensure you’ve included or added all the replacement strings as I showed you above:
replace "oldstring" "newstring" -- *
at the end of the file /bin/replace_string_files_present_dir.
To add a new replace string just open the script we created by typing the following in the terminal:
sudo gedit /bin/replace_string_files_present_dir
Don’t worry about the number of replace strings you add, they will have no effect if the oldstring is not found.
1. Replacing all occurrences of one string with another in all files in the current directory:
These are for cases where you know that the directory contains only regular files and that you want to process all non-hidden files. If that is not the case, use the approaches in 2.
All sed
solutions in this answer assume GNU sed
. If using FreeBSD or macOS, replace -i
with -i ''
. Also note that the use of the -i
switch with any version of sed
has certain filesystem security implications and is inadvisable in any script which you plan to distribute in any way.
-
Non recursive, files in this directory only:
sed -i -- 's/foo/bar/g' * perl -i -pe 's/foo/bar/g' ./*
(the perl
one will fail for file names ending in |
or space)).
-
Recursive, regular files (including hidden ones) in this and all subdirectories
find . -type f -exec sed -i 's/foo/bar/g' {} +
If you are using zsh:
sed -i -- 's/foo/bar/g' **/*(D.)
(may fail if the list is too big, see
zargs
to work around).Bash can’t check directly for regular files, a loop is needed (braces avoid setting the options globally):
( shopt -s globstar dotglob; for file in **; do if [[ -f $file ]] && [[ -w $file ]]; then sed -i -- 's/foo/bar/g' "$file" fi done )
The files are selected when they are actual files (-f) and they are writable (-w).
2. Replace only if the file name matches another string / has a specific extension / is of a certain type etc:
-
Non-recursive, files in this directory only:
sed -i -- 's/foo/bar/g' *baz* ## all files whose name contains baz sed -i -- 's/foo/bar/g' *.baz ## files ending in .baz
-
Recursive, regular files in this and all subdirectories
find . -type f -name "*baz*" -exec sed -i 's/foo/bar/g' {} +
If you are using bash (braces avoid setting the options globally):
( shopt -s globstar dotglob sed -i -- 's/foo/bar/g' **baz* sed -i -- 's/foo/bar/g' **.baz )
If you are using zsh:
sed -i -- 's/foo/bar/g' **/*baz*(D.) sed -i -- 's/foo/bar/g' **/*.baz(D.)
The --
serves to tell sed
that no more flags will be given in the command line. This is useful to protect against file names starting with -
.
-
If a file is of a certain type, for example, executable (see
man find
for more options):find . -type f -executable -exec sed -i 's/foo/bar/g' {} +
zsh
:
sed -i -- 's/foo/bar/g' **/*(D*)
3. Replace only if the string is found in a certain context
-
Replace
foo
withbar
only if there is abaz
later on the same line:sed -i 's/foo(.*baz)/bar1/' file
In sed
, using ( )
saves whatever is in the parentheses and you can then access it with 1
. There are many variations of this theme, to learn more about such regular expressions, see here.
-
Replace
foo
withbar
only iffoo
is found on the 3d column (field) of the input file (assuming whitespace-separated fields):gawk -i inplace '{gsub(/foo/,"baz",$3); print}' file
(needs gawk
4.1.0 or newer).
-
For a different field just use
$N
whereN
is the number of the field of interest. For a different field separator (:
in this example) use:gawk -i inplace -F':' '{gsub(/foo/,"baz",$3);print}' file
Another solution using perl
:
perl -i -ane '$F[2]=~s/foo/baz/g; $" = " "; print "@Fn"' foo
NOTE: both the awk
and perl
solutions will affect spacing in the file (remove the leading and trailing blanks, and convert sequences of blanks to one space character in those lines that match). For a different field, use $F[N-1]
where N
is the field number you want and for a different field separator use (the $"=":"
sets the output field separator to :
):
perl -i -F':' -ane '$F[2]=~s/foo/baz/g; $"=":";print "@F"' foo
-
Replace
foo
withbar
only on the 4th line:sed -i '4s/foo/bar/g' file gawk -i inplace 'NR==4{gsub(/foo/,"baz")};1' file perl -i -pe 's/foo/bar/g if $.==4' file
4. Multiple replace operations: replace with different strings
-
You can combine
sed
commands:sed -i 's/foo/bar/g; s/baz/zab/g; s/Alice/Joan/g' file
Be aware that order matters (sed 's/foo/bar/g; s/bar/baz/g'
will substitute foo
with baz
).
-
or Perl commands
perl -i -pe 's/foo/bar/g; s/baz/zab/g; s/Alice/Joan/g' file
-
If you have a large number of patterns, it is easier to save your patterns and their replacements in a
sed
script file:#! /usr/bin/sed -f s/foo/bar/g s/baz/zab/g
-
Or, if you have too many pattern pairs for the above to be feasible, you can read pattern pairs from a file (two space separated patterns, $pattern and $replacement, per line):
while read -r pattern replacement; do sed -i "s/$pattern/$replacement/" file done < patterns.txt
-
That will be quite slow for long lists of patterns and large data files so you might want to read the patterns and create a
sed
script from them instead. The following assumes a <<!>space<!>> delimiter separates a list of MATCH<<!>space<!>>REPLACE pairs occurring one-per-line in the filepatterns.txt
:sed 's| *([^ ]*) *([^ ]*).*|s/1/2/g|' <patterns.txt | sed -f- ./editfile >outfile
The above format is largely arbitrary and, for example, doesn’t allow for a <<!>space<!>> in either of MATCH or REPLACE. The method is very general though: basically, if you can create an output stream which looks like a sed
script, then you can source that stream as a sed
script by specifying sed
‘s script file as -
stdin.
-
You can combine and concatenate multiple scripts in similar fashion:
SOME_PIPELINE | sed -e'#some expression script' -f./script_file -f- -e'#more inline expressions' ./actual_edit_file >./outfile
A POSIX sed
will concatenate all scripts into one in the order they appear on the command-line. None of these need end in a n
ewline.
-
grep
can work the same way:sed -e'#generate a pattern list' <in | grep -f- ./grepped_file
-
When working with fixed-strings as patterns, it is good practice to escape regular expression metacharacters. You can do this rather easily:
sed 's/[]$&^*./[]/\&/g s| *([^ ]*) *([^ ]*).*|s/1/2/g| ' <patterns.txt | sed -f- ./editfile >outfile
5. Multiple replace operations: replace multiple patterns with the same string
-
Replace any of
foo
,bar
orbaz
withfoobar
sed -Ei 's/foo|bar|baz/foobar/g' file
-
or
perl -i -pe 's/foo|bar|baz/foobar/g' file
6. Replace File paths in multiple files
Another use case of using different delimiter:
sed -i 's|path/to/foo|path/to/bar|g' *
Question: How do I replace all occurrences of a word in all the files in the given folder?
Consider a problem scenario where you have a website in which you often refer to the current year. Every year you need to update the year. You can easily find all occurrences in all the files but manually changing the year, one by one, in each file should be avoided.
Solution
So, what do you do? One of the several ways to find all occurrences and then replace the searched term is by using a combination of find and sed commands.
You can easily do so with a single command: In this example, you have 50 web pages in the pages folder. This command will instantly change all occurrences of “2017” to “2018”:
find ~/public_html/my_website/pages -type f -exec sed -i 's/2017/2018/g' {} ;
To make the above example a bit more generic, here’s what you need to do:
find <path_to_directory> -type f -exec sed -i 's/<search_text>/<replace_text>/g' {} ;
In the above command, replace <path_to_directory>, <search_text> and <replace_text> with the actual data.
Explanation
What you are doing here is that you are using find command to get all the files in the current directories and its sub-directories. The -type f option makes sure that you only get files, not directories.
And then you pass the result of find command using the exec command to the sed command. The sed command searches for the text and replaces it.
The {} ; is part of the exec command. The space between } and is mandatory.
This Linux quick tip was suggested by Linux Handbook reader, Jane Hadley. Got a better solution for this problem? Share it in the comments.
Creator of Linux Handbook and It’s FOSS. An ardent Linux user & open source promoter. Huge fan of classic detective mysteries from Agatha Christie and Sherlock Holmes to Columbo & Ellery Queen.
What do you do if you have to replace a single word in dozens or even thousands, of text files? You keep calm and download Notepad++ or Replace Text to do the job in seconds.
What do you do if you have to replace a single word in dozens, or even hundreds or thousands, of text files? You keep calm and download Notepad++ [Broken URL Removed] or Replace Text [No Longer Available]. These two utilities will do the job in seconds.
It’s a dilemma common among developers and programmers. Imagine you’re managing a project with hundreds or thousands of files. When a product name that appears on almost every page changes, you can hardly go through each page to manually search and change the name. No, you’re smarter than that.
You fire up Google, you find this article, and you learn about a solution that only takes seconds.
How to Edit Multiple Files in Bulk
You can either use Notepad++ or a dedicated tool called Replace Text to bulk-edit your files.
Notepad++
First, allow Notepad++ to find the word in all the files you need to edit. Open Notepad++ and go to Search > Find in Files… or press CTRL+SHIFT+F. This opes the Find in Files menu.
Under Find what:, enter the word or phrase that you need to change. Under Replace with:, enter the new word or phrase. Finally, set the Directory: where the affected files are located, so that Notepad++ knows where to search.
You can also use advanced settings, which I’ve outlined further down. When all is set, click Find All if you need to double-check the hits or Replace in Files if you want Notepad++ to immediately apply the changes. Depending on the number of files Notepad++ is searching, this can take a few seconds.
If you went with Find All, you’ll get a list of hits. Remove all the files you don’t want to edit by selecting them and pressing DEL, then right-click the remaining files and choose Open all.
Now go to Search > Replace or press CTRL+H, which will launch the Replace menu. Here you’ll find an option to Replace All in All Opened Documents.
Again, you can make several advanced settings, as explained below.
Advanced Search and Replace Settings in Notepad++
Under Find in Files, you can add Filters to search only in certain file types. For example, add *.doc to search only in DOC files. Likewise, you can search for files with a certain name, regardless of file type. Add *.* to search any file name and type.
When you choose a directory with sub-folders, check In all sub-folders and In hidden folders to search those, too. You might also want to check Match whole word only, so you don’t accidentally edit a partial match.
The Search Mode in both the Find in Files and Replace menus allows you to make advanced searches and replacements. Select Extended if you are using extensions, for example to replace a character with a new line (n). Select Regular expression if you’re using operators to find and replace all matching words or phrases. You can stick with Normal if you’re just replacing text with text.
Replace Text [No Longer Available]
With Replace Text, you can set up a Replace Group to add multiple files and/or directories and multiple replacements.
To start, create a new group. Go to Replace > Add Group, and give your group a name.
Right-click your group and select Add File(s)… to add the files and/or folders you want to edit. In the Files / Folder Properties, select your Source Type, i.e., a single file or folder, then choose the Source File / Folder Path. If you choose to add a folder, you can also include and exclude file types by adding them to the Include File Filter or Exclude File Filter rows. Click OK when you’re done.
To add multiple files or folders, repeat the above step.
Replace Text’s best feature is that you can choose a destination that’s different from the original location. In the File / Folder Properties, switch to the Destination tab and choose your desired Destination File / Folder Path.
Now that you’ve set up your group, it’s time to define your replacements. Select your group and go to Replace > Search/Replace Grid > Advanced Edit… Now you can add the Search Text and Replace Text. Be sure to look in the drop-down menu at the bottom to customize the search and replace options.
Like with Notepad++, you can use advanced search strings and operators. Unlike Notepad++, you can add as many search and replace instances as you like and Replace Text will run through all of them when you run the process.
To make the replacements, go to Replace > Start Replacing or press CTRL+R.
What Is Notepad++?
Notepad++ is a free source code editor and Windows Notepad alternative. It’s released under a GNU General Public License, making it an open-source tool.
Furthermore, Notepad++ is a lightweight application that conserves resources, which makes it good for the environment:
By optimizing as many routines as possible without losing user friendliness, Notepad++ is trying to reduce the world carbon dioxide emissions. When using less CPU power, the PC can throttle down and reduce power consumption, resulting in a greener environment.
Here’s a small selection of Notepad++ features that make this the perfect tool for writing and editing (code):
-
Numbered lines for easier navigation.
-
Automatic and customizable highlighting and folding of coding syntax.
-
Support for Perl Compatible Regular Expression (PCRE) search-and-replace.
-
Auto-completion that includes word completion, function completion, and function parameters hint.
-
A tabbed interface that lets you work with multiple documents in parallel.
-
Editing of multiple lines at once, using either CTRL+mouse-selection or column editing.
What Is Replace Text?
Replace Text is a whole lot simpler than Notepad++. It does one job: replacing text. Ecobyte, the company behind Replace Text, is mindful of its impact. Hence, the software with a cause comes with an unusual EULA:
Unfortunately, Replace Text is no longer supported and no help file is available in Windows 10. I have covered it anyhow because it offers more advanced features than Notepad++ for this particular application.
Search and Replace Made Easy
One of the two utilities above should do the job for you. If you only have a simple search-and-replace job or if the additional features of Notepad++ sound useful, you should give it a try. If you need to edit not only multiple files, but also need to make multiple different replacements, it’s worth looking into Replace Text.
Which one did you choose and did it work as prescribed? Have you found other tools that can search-and-replace text? Let us know in the comments below!
Image Credit: Fabrik Bilder via Shutterstock.com