Recursive search and replace in text files on Mac and Linux
OS X uses a mix of BSD and GNU tools, so best always check the documentation (although I had it that less
didn't even conform to the OS X manpage):
https://web.archive.org/web/20170808213955/https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man1/sed.1.html
sed takes the argument after -i
as the extension for backups. Provide an empty string (-i ''
) for no backups.
The following should do:
find . -type f -name '*.txt' -exec sed -i '' s/this/that/g {} +
The -type f
is just good practice; sed will complain if you give it a directory or so.
-exec
is preferred over xargs
; you needn't bother with -print0
or anything.
The {} +
at the end means that find
will append all results as arguments to one instance of the called command, instead of re-running it for each result. (One exception is when the maximal number of command-line arguments allowed by the OS is breached; in that case find
will run more than one instance.)
If you get an error like "invalid byte sequence," it might help to force the standard locale by adding LC_ALL=C
at the start of the command, like so:
LC_ALL=C find . -type f -name '*.txt' -exec sed -i '' s/this/that/g {} +
Can I search/replace in multiple .txt files quickly from Terminal?
GNU sed
:
sed -i 's/--/—/g' *.txt
OSX BSD sed
:
You need to specify a backup file extension. To create a backup file with the extension: .txt.bak
:
sed -i '.bak' 's/--/—/g' *.txt
To completely replace the files, specify an empty extension:
sed -i '' 's/--/—/g' *.txt
How do I recursively search and replace directory paths in terminal Mac?
Remove / which is present in before curly braces in your command, that is
find . -type f -name '*.txt' -exec sed -i '' s%localhost/massignition%www.site.com% {} +
instead of
find . -type f -name '*.txt' -exec sed -i '' s%localhost/massignition%www.site.com%/ {} +
How to do a recursive find and replace from the command line?
The simplest (and arguably most pure and intuitive) way to achieve this is to perform a recursive file grep
then pipe those file results to sed (via xargs
) to handle the in-place substitution.
grep -r -l "port" | xargs -r -d'\n' sed -i 's/port/port-lookup/g'
There is a comprehensive community wiki answer on this topic that I would recommend reading over on the Unix & Linux exchange.
Search and replace a word in directory and its subdirectories
You could do a pure Perl solution that recursively traverses your directory structure, but that'd require a lot more code to write.
The easier solution is to use the find
command which can be told to find all files and run a command against them.
find . -type f -exec perl -pi -w -e 's/foo/bar/g;' \{\} \;
(I've escaped the {} and ; just in case but you might not need this)
How to replace a string in multiple files in linux command line
cd /path/to/your/folder
sed -i 's/foo/bar/g' *
Occurrences of "foo" will be replaced with "bar".
On BSD systems like macOS, you need to provide a backup extension like -i '.bak'
or else "risk corruption or partial content" per the manpage.
cd /path/to/your/folder
sed -i '.bak' 's/foo/bar/g' *
Related Topics
How to Execute Ssh-Keygen Without Prompt
What Do the Numbers in /Proc/Loadavg Mean on Linux
Linux: Command to Open Url in Default Browser
How to Upgrade Aws Cli to the Latest Version
File Names with Spaces in Bash
Ioctl VS Netlink VS Memmap to Communicate Between Kernel Space and User Space
Linking 32-Bit Library to 64-Bit Program
How Does Vi Restore Terminal Content After Quitting It
How to Read Single Character Input from Keyboard Using Nasm (Assembly) Under Ubuntu
Converting Jiffies to Milli Seconds
How to Attach a File Using Mail Command on Linux
How to Change the Filename of a Shared Library After Building a Program That Depends on It
How to Filter Out All Unique Lines in a File
Linux Removing Folders Older Than 1 Year and More Than 3 Files