How to do a recursive find/replace of a string wit

2018-12-31 14:41发布

How do I find and replace every occurrence of:

subdomainA.example.com

with

subdomainB.example.com

in every text file under the /home/www/ directory tree recursively?

30条回答
临风纵饮
2楼-- · 2018-12-31 15:01
find /home/www/ -type f -exec perl -i.bak -pe 's/subdomainA\.example\.com/subdomainB.example.com/g' {} +

find /home/www/ -type f will list all files in /home/www/ (and its subdirectories). The "-exec" flag tells find to run the following command on each file found.

perl -i.bak -pe 's/subdomainA\.example\.com/subdomainB.example.com/g' {} +

is the command run on the files (many at a time). The {} gets replaced by file names. The + at the end of the command tells find to build one command for many filenames.

Per the find man page: "The command line is built in much the same way that xargs builds its command lines."

Thus it's possible to achieve your goal (and handle filenames containing spaces) without using xargs -0, or -print0.

查看更多
栀子花@的思念
3楼-- · 2018-12-31 15:03

grep -lr 'subdomainA.example.com' | while read file; do sed -i "s/subdomainA.example.com/subdomainB.example.com/g" "$file"; done

I guess most people don't know that they can pipe something into a "while read file" and it avoids those nasty -print0 args, while presevering spaces in filenames.

Further adding an echo before the sed allows you to see what files will change before actually doing it.

查看更多
谁念西风独自凉
4楼-- · 2018-12-31 15:03

to change multiple files (and saving a backup as *.bak):

perl -p -i -e "s/\|/x/g" *

will take all files in directory and replace | with x called a “Perl pie” (easy as a pie)

查看更多
零度萤火
5楼-- · 2018-12-31 15:05

I just needed this and was not happy with the speed of the available examples. So I came up with my own:

cd /var/www && ack-grep -l --print0 subdomainA.example.com | xargs -0 perl -i.bak -pe 's/subdomainA\.example\.com/subdomainB.example.com/g'

Ack-grep is very efficient on finding relevant files. This command replaced ~145 000 files with a breeze whereas others took so long I couldn't wait until they finish.

查看更多
路过你的时光
6楼-- · 2018-12-31 15:09

A bit old school but this worked on OS X.

There are few trickeries:

• Will only edit files with extension .sls under the current directory

. must be escaped to ensure sed does not evaluate them as "any character"

, is used as the sed delimiter instead of the usual /

Also note this is to edit a Jinja template to pass a variable in the path of an import (but this is off topic).

First, verify your sed command does what you want (this will only print the changes to stdout, it will not change the files):

for file in $(find . -name *.sls -type f); do echo -e "\n$file: "; sed 's,foo\.bar,foo/bar/\"+baz+\"/,g' $file; done

Edit the sed command as needed, once you are ready to make changes:

for file in $(find . -name *.sls -type f); do echo -e "\n$file: "; sed -i '' 's,foo\.bar,foo/bar/\"+baz+\"/,g' $file; done

Note the -i '' in the sed command, I did not want to create a backup of the original files (as explained in In-place edits with sed on OS X or in Robert Lujo's comment in this page).

Happy seding folks!

查看更多
荒废的爱情
7楼-- · 2018-12-31 15:11

An one nice oneliner as an extra. Using git grep.

git grep -lz 'subdomainA.example.com' | xargs -0 perl -i'' -pE "s/subdomainA.example.com/subdomainB.example.com/g"
查看更多
登录 后发表回答