Wednesday, March 16, 2011

How do I replace 'php3' with 'php' inside every file in a directory.

Hopefully a nice simple one.

I've got a php3 website that I want to run on php 5.2

To start with I'd just like to have every reference to the current "index.php3" _within_each_file_ (recursively) changed to "index.php" and then move on to worrying about globals etc.

K. Go!

:)

Update: Thanks a lot! I realise that my question missed the fact that the references are in each file of a website and I wanted to do it recursively in all files/folders.

From stackoverflow
  • sed -i 's/php3/php/g' *

    Assuming you are using a unix-like operating system.

    Jonathan Leffler : And one with GNU sed -- that won't work with non-GNU versions of sed.
    paxdiablo : Minor nitpick, @Jonathan - you'd be hard-pressed trying to find a UNIX without GNU sed nowadays.
    Brian C. Lane : Find me a Unix-like system running PHP that doesn't have a GNU version of sed :)
    Bill Karwin : @Brian: any BSD-based machine, like FreeBSD, NetBSD, or Mac OS X.
    Jonathan Leffler : Solaris, AIX, HP-UX, to name but three.
  • How about:

    for file in *.php3
    do
        sed 's/\.php3/.php/g' $file > ${file%3}
    done
    

    The for/do/done loop deals with each .php3 file in turn, editing the file and replacing each string .php3 with .php, and copying the file from something.php3 to something.php.

    Added for amended question:

    for file in $(find . -type f -name '*.php3' -print)
    do
        sed 's/\.php3/.php/g' $file > ${file%3}
    done
    

    The '-print' can usually be omitted these days, but historically, a lot of machine time was wasted by people who forgot to add it because there was originally (pre-POSIX) no default action.

    This fragment is about the simplest modification of the original code to do the extended task, but isn't necessarily the best way to do it any more - it pre-generates the entire list of files before processing any. You could instead use:

    find . -type f -name '*.php3' -print |
    while read file
    do
        sed 's/\.php3/.php/g' $file > ${file%3}
    done
    

    However, both the amended versions can run into problems if file names or path names can contain blanks or newlines or other such characters. To avoid such issues, you have to work harder - using Perl or (GNU find + xargs) or some other techniques. If you're sane, you avoid such problems. If you've inherited a less than entirely sane setup, then you may have to delve deeper into the arcana of Unix file name handling.

    gyaresu : Hey Jonathan. Thanks but I need to change the php3 reference inside each file. The only file with php3 is index.php3 and that's what all the code is calling :) hence the need to change. Cheers.
    Jonathan Leffler : The basic technique remains the same - tweaking the details is the main difference. If the files are already renamed, then use 'sed ... $file >tmp.$$; mv $file old.$file; mv tmp.$$ $file', for example. Or use 'perl -i.bak' and appropriate code. Or ...
  • To do this recursively, use Jonathan's answer but substitute find . -type f for *.php3. Note that the back ticks are important and you can substitute any directory for "." (i.e. the current directory). Here is a version that also renames the file in the process (*.php3 -> *.php).

    #!/bin/bash
    for file in `find . -type f`
    do
        sed 's/\.php3/\.php/g' $file > ${file//3/}
        rm $file
    done
    
    gyaresu : Hey ctuffli I made the script in the root of the webdir (a fresh copy of course) and ran it. It ate all the files in the directory except for index.php (which it renamed). Quite the odd outcome.
    ctuffli : Under which OS did you try this? The script didn't eat any files on my OS X system.
  • find -type f -exec perl -pi -e 's/\bindex\.php3\b/index.php/g' {} \;
    
    gyaresu : Thanks Joshua! Worked perfectly.

0 comments:

Post a Comment