Search and Replace Recursively using sed and grep on Linux/Mac
I have done this so many times, still I find a new problem doing recursive search and replace each time!
Here's one just only one line command(it could be running in terminal) that puts the issues I had on the Mac/Linux doing search and replace on a match files recursively.
$ for i in $(grep -ril 'old_pattern' *); do sed "s/old_pattern/new_pattern/g" "$i" > tmp && \mv tmp "$i"; done
Below is the other ways to do search & replace patterns, which is also a single line, it just could be run on Linux only(Mac not support such programming syntax:eg.「$ sed -i ⋯」 or 「sed 's/⋯/⋯/g'」; for the later case, it just cannot work in shell script; for the first case, it cannot work both in terminal & shell script):
$ for i in $(grep -ril 'old_pattern' *); do sed -i 's/old_pattern/new_pattern/g' "$i"; done
&
$ sed -i 's/old_pattern/new_pattern/g' `grep -ril 'old_pattern' *`
The following script-shell code segment was shown as below, it could be work that doing search and replace on a directory recursively under the Mac/Linux.
#!/bin/sh grep -rl $2 $1 | while read filename do ( echo $filename sed "s/$2/$3/g;" $filename> $filename.xx mv $filename.xx $filename ) done
Save the file as rpl.sh, chmod it 755, and execute it like:
$ ./rpl.sh folderContainingFiles/ oldPattern newPattern
Below is an another ways to do search & replace pattern without directory parameter under Mac/Linux.
#!/bin/bash usage() { echo "replaceStr <pattern> <new pattern>" } filerep() { for i in $(grep -ril $1 *); do sed "s/$1/$2/g" "$i" > tmp && \mv tmp "$i"; done } if [ -z "$1" ]; then echo "It need the first argument." usage elif [ -z "$2" ]; then echo "It need the second argument." usage else if test "$1" && test "$2" then filerep $1 $2 fi fi
Save the file as replacePattern.sh, chmod it 755, and execute it like:
$ replacePattern.sh <pattern> <newPattern>
&
#!/bin/sh # To replace pattern by new pattern for match files. usage() { echo "replacefile.sh text newtext" } filerep() { # if grep "$1" "$filename" > /dev/null 2>&1 # then echo "convert \"$2\" into \"$3\" in $filename" filetmp="$filename.tmp" echo "sed \"s/$2/$3/g\" $1 > $filetmp" sed "s/$2/$3/g;" $1 > $filetmp echo "\mv -f $filetmp $filename" \mv -f $filetmp $filename # else # echo "do nothing for $1 in $filename" # fi } if [ -z "$1" ]; then echo "Need first argument." usage elif [ -z "$2" ]; then echo "Need second argument." usage else if test "$1" && test "$2" then dir=`grep -ril "$1" *` echo "match files : $dir" for filename in $dir do filerep "$filename" "$1" "$2" done fi fi
Save the file as replaceFileText.sh, chmod it 755, and execute it like:
$ replaceFileText.sh <pattern> <newPattern>
「replaceFileText.sh」is modified from replaceall.sh .
Both replacePattern.sh & replaceFileText.sh could be work on Mac/Linux.
留言列表