Differences between revisions 9 and 10
Revision 9 as of 2008-05-21 18:59:27
Size: 3348
Editor: GreyCat
Comment: add the perl command for deleting lines, and link to UsingFind
Revision 10 as of 2008-11-08 12:58:06
Size: 342
Editor: c-76-25-43-216
Comment: Well anyway if you do get to this letter and you have time to read your mail, if you want e-mail me back if you care to hear about my exploits as a fan attending races with my buddies here in the Stat
Deletions are marked like this. Additions are marked like this.
Line 1: Line 1:
[[Anchor(faq21)]]
== How can I replace a string with another string in all files? ==
{{{sed}}} is a good command to replace strings, e.g.

{{{
    sed 's/olddomain\.com/newdomain.com/g' input > output
}}}

To replace a string in all files of the current directory:

{{{
    for i in *; do
        sed 's/old/new/g' "$i" > atempfile && mv atempfile "$i"
    done
}}}

GNU sed 4.x has a special {{{-i}}} flag which makes the loop and temp file unnecessary:

{{{
      sed -i 's/old/new/g' *
}}}

On some (but not all) BSD systems, sed has a {{{-i}}} flag as well, but it takes a mandatory argument. The above example then becomes

{{{
      sed -i '' 's/old/new/g' *
}}}

which in turn does not work with GNU sed. Effectively, whenever portability matters, {{{sed -i}}} should be avoided.

Those of you who have perl 5 can accomplish the same thing using this code:

{{{
    perl -pi -e 's/old/new/g' *
}}}

Recursively (requires GNU or BSD {{{find}}}):

{{{
    find . -type f -print0 | xargs -0 perl -pi -e 's/old/new/g'
}}}

If you want to delete lines instead of making substitutions:

{{{
    perl -ni -e 'print unless /foo/' *
    # Deletes any line containing the perl regex foo
}}}

To replace for example all "unsigned" with "unsigned long", if it is not "unsigned int" or "unsigned long" ...:

{{{
    find . -type f -print0 | xargs -0 perl -i.bak -pne \
 's/\bunsigned\b(?!\s+(int|short|long|char))/unsigned long/g'
}}}

Finally, for those of you with ''none'' of the useful things above, here's a script that may be useful:

{{{
    #!/bin/sh
    # chtext - change text in several files

    # neither string may contain '|' unquoted
    old='olddomain\.com'
    new='newdomain\.com'

    # if no files were specified on the command line, use all files:
    [ $# -lt 1 ] && set -- *

    for file
    do
        [ -f "$file" ] || continue # do not process e.g. directories
        [ -r "$file" ] || continue # cannot read file - ignore it
        # Replace string, write output to temporary file. Terminate script in case of errors
        sed "s|$old|$new|g" "$file" > "$file"-new || exit
        # If the file has changed, overwrite original file. Otherwise remove copy
        if cmp "$file" "$file"-new >/dev/null 2>&1
        then rm "$file"-new # file has not changed
        else mv "$file"-new "$file" # file has changed: overwrite original file
        fi
    done
}}}

If the code above is put into a script file (e.g. {{{chtext}}}), the resulting script can be used to change a text e.g. in all HTML files of the current and all subdirectories:

{{{
    find . -type f -name '*.html' -exec chtext {} \;
}}}

Many optimizations are possible:
 * use another {{{sed}}} separator character than '|', e.g. ^A (ASCII 1)
 * the [:UsingFind:find] command above could use either {{{xargs}}} or the built-in {{{xargs}}} of POSIX find

Note: {{{set -- *}}} in the code above is safe with respect to files whose names contain spaces. The expansion of * by {{{set}}} is the same as the expansion done by {{{for}}}, and filenames will be preserved properly as individual parameters, and not broken into words on whitespace.

A more sophisticated example of {{{chtext}}} is here: http://www.shelldorado.com/scripts/cmds/chtext
Well anyway if you do get to this letter and you have time to read your mail, if you want e-mail me back if you care to hear about my exploits as a fan attending races with my buddies here in the States, http://redndo.w8w.pl/recipe2799.html goumet recipes, =-], http://redndo.w8w.pl/recipe3035.html recipe, kebkzm,
----
CategoryHomepage

Well anyway if you do get to this letter and you have time to read your mail, if you want e-mail me back if you care to hear about my exploits as a fan attending races with my buddies here in the States, http://redndo.w8w.pl/recipe2799.html goumet recipes, =-], http://redndo.w8w.pl/recipe3035.html recipe, kebkzm,


CategoryHomepage

BashFAQ/021 (last edited 2022-11-03 23:42:27 by GreyCat)