1

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

Community
  • 1
  • 1
jml
  • 1,745
  • 6
  • 29
  • 55
  • Possible duplicate: http://stackoverflow.com/questions/8905662/how-to-change-all-occurances-of-a-word-in-all-files-in-a-directory/ – Dan Fego Jan 18 '12 at 19:41
  • I'm also asking a question about perl, and in general what the advantage of getting into one methodology over the other would be. – jml Jan 18 '12 at 19:47
  • I'm also specifically wondering about a solution to the perl problem regarding directories... – jml Jan 18 '12 at 19:50

3 Answers3

7
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
ikegami
  • 367,544
  • 15
  • 269
  • 518
  • that works better (at least it writes to more files), but i still get errors regarding the "can't do inplace edit" thing. – jml Jan 18 '12 at 19:58
  • @jml, oh! I think you used the code that was missing `-type f`. It was there for just a few seconds! That's what's preventing "is not a regular file". – ikegami Jan 18 '12 at 20:25
1

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).

jcollado
  • 39,419
  • 8
  • 102
  • 133
0

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.

xpapad
  • 4,376
  • 1
  • 24
  • 25