jml
jml

Reputation: 1806

unix find and replace text in dir and subdirs

I'm trying to change the name of "my-silly-home-page-name.html" to "index.html" in all documents within a given master directory and subdirs.

I saw this: Shell script - search and replace text in multiple files using a list of strings.

And this: How to change all occurrences of a word in all files in a directory

I have tried this:

grep -r "my-silly-home-page-name.html" .

This finds the lines on which the text exists, but now I would like to substitute 'my-silly-home-page-name' for 'index'. How would I do this with sed or perl? Or do I even need sed/perl?

Something like:

grep -r "my-silly-home-page-name.html" . | sed 's/$1/'index'/g'

?

Also; I am trying this with perl, and I try the following:

perl -i -p -e 's/my-silly-home-page-name\.html/index\.html/g' *

This works, but I get an error when perl encounters directories, saying "Can't do inplace edit: SOMEDIR-NAME is not a regular file, <> line N"

Thanks, jml

Upvotes: 1

Views: 5944

Answers (3)

ikegami
ikegami

Reputation: 385789

find . -type f -exec \
   perl -i -pe's/my-silly-home-page-name(?=\.html)/index/g' {} +

Or if your find doesn't support -exec +,

find . -type f -print0 | xargs -0 \
   perl -i -pe's/my-silly-home-page-name(?=\.html)/index/g'

Both pass to Perl as arguments as many names at a time as possible. Both work with any file name, including those that contains newlines.


If you are on Windows and you are using a Windows build of Perl (as opposed to a cygwin build), -i won't work unless you also do a backup of the original. Change -i to -i.bak. You can then go and delete the backups using

find . -type f -name '*.bak' -delete

Upvotes: 7

jcollado
jcollado

Reputation: 40384

This should do the job:

find . -type f -print0 | xargs -0 sed -e 's/my-silly-home-page-name\.html/index\.html/g' -i

Basically it gathers recursively all the files from the given directory (. in the example) with find and runs sed with the same substitution command as in the perl command in the question through xargs.

Regarding the question about sed vs. perl, I'd say that you should use the one you're more comfortable with since I don't expect huge differences (the substitution command is the same one after all).

Upvotes: 1

xpapad
xpapad

Reputation: 4456

There are probably better ways to do this but you can use:

find . -name oldname.html |perl -e 'map { s/[\r\n]//g; $old = $_; s/oldname.txt$/newname.html/; rename  $old,$_  } <>';

Fyi, grep searches for a pattern; find searches for files.

Upvotes: 0

Related Questions