Recursive Search and Replace in Text Files on MAC and Linux

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



Leave a reply



Submit