Size: 2946
Comment: removed loop for sed -i
|
Size: 2901
Comment: clean-up
|
Deletions are marked like this. | Additions are marked like this. |
Line 6: | Line 6: |
sed 's/olddomain\.com/newdomain\.com/g' input > output | sed 's/olddomain\.com/newdomain.com/g' input > output |
Line 29: | Line 29: |
Recursively: | Recursively (requires GNU or BSD {{{find}}}): |
Line 38: | Line 38: |
perl -i.bak -pne 's/\bunsigned\b(?!\s+(int|short|long|char))/unsigned long/g' $(find . -type f) | find . -type f -print0 | xargs -0 perl -i.bak -pne \ 's/\bunsigned\b(?!\s+(int|short|long|char))/unsigned long/g' |
Line 42: | Line 43: |
Finally, here's a script that some people may find useful: | Finally, for those of you with ''none'' of the useful things above, here's a script that may be useful: |
Line 45: | Line 46: |
: | #!/bin/sh |
Line 77: | Line 78: |
* some implementations of {{{sed}}} (e.g. GNU sed) have an "-i" option that can change a file in-place; no temporary file is necessary in that case |
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 (but no other version of sed) has a special -i flag which makes the loop and temp file unnecessary:
sed -i 's/old/new/g' *
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'
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 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