Skip to content

Instantly share code, notes, and snippets.

@peterhost
Created November 12, 2010 16:52
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save peterhost/674341 to your computer and use it in GitHub Desktop.
Save peterhost/674341 to your computer and use it in GitHub Desktop.
FIND string in files: bash script to easilly find a given string in all files of a given type in the current directory and its subdirectories (.git dirs excluded) and print the results with some colors
# ---------------------------------------------------------------------------
# FIND string in (regular) files
# https://gist.github.com/674341
# -> finds a given string in all files of a given type in the current
# directory and its subdirectories (.git directory contents excluded,
# directories excluded)
function findall()
{
#CUSTOM COLORS : declare them as local variables so as not to clutter your BASH ENVIRONMENT
local NONE="\033[0m" # unsets color to term's fg color
local EM="\033[1m" #bold
local UN="\033[4m" #underline
local EMQ="\033[21m" #END bold
local UNQ="\033[24m" #END underline
local R="\033[0;31m" # red
local G="\033[0;32m" # green
local GR="\033[0;30m" # grey
local EMY="\033[1;33m" # bold yellow
local Y="\033[0;33m" # yellow
local B="\033[0;34m" # blue
local EMB="\033[1;34m" # bold blue
local EMM="\033[1;35m" # bold magenta
local C="\033[0;36m" # cyan
local W="\033[0;37m" # white
local args_=$# string_ pattern_ verbose_ detail_ exclude_ exclude_all_ include_ include_all_ quiet_ rfc_
local findCommand_
local findCommand_1="find . -wholename './*.git' -prune -o -type f -name '"
local findCommand_2="' "
local findCommand_3=" -print0 " # pre-build find command
local debugFindCommand_ # for printing the whole pipe if --debug
local log__ debug_="0"
# *NIX sniffing
# reason : I prefer using the --extended-regexp option of `sed` (closer to perl's and cleaner).
# Hence the OS sniffing (only there for that purpose). Feel free to adapt to `sed -e`
# instead (and contribute back the result!)
if uname -s | grep "Darwin" >/dev/null 2>&1; then OSflavor="Darwin" # macos
fi
if uname -s | grep -E "FreeBSD|BSD\/OS" >/dev/null 2>&1; then OSflavor="BSD" # FreeBSD, BSD
fi
local sedEPrefix_ sedNumber_ sedSpace_ sedSpaceDbg_
if [[ "$OSflavor" =~ Darwin || "$OSflavor" =~ BSD ]]; then sedEPrefix_="sed -E "; else sedEPrefix_="sed -r "; fi
sedSpace_=$sedEPrefix_" 's/[[:space:]]+/\\\\ /g'" #used for escaping spaces in filenames when we can't just do it with xargs -0
# backslashes escaped twice because $sedSpace_ will be evalled; so \\\\ will be turned into \\
# which is what we want as a regexp ( s/[[:space:]]+/\\ /g )
sedNumber_=$sedEPrefix_" 's/^[[:space:]]+[0-9]+[[:space:]]+//'" # used by findall_detail()
# FILE exclusion Patterns
# FEEL free to augment these
local EXCL_f_image_=' ! -name "*.jpg" ! -name "*.jpeg" ! -name "*.gif" ! -name "*.png" ! -name "*.tif" ! -name "*.tiff" ! -name "*.psd" ! -name "*.ico" ! -name "*.tga" '
local EXCL_f_archive_=' ! -name "*.zip" ! -name "*.rar" ! -name "*.gz" ! -name "*.bz" ! -name "*.bz2" ! -name "*.tar" '
local EXCL_f_script_=' ! -name "*.pl" ! -name "*.rb" ! -name "*.sh" ! -name "*.py" '
local EXCL_f_html_=' ! -name "*.htm" ! -name "*.html" ! -name "*.php" ! -name "*.css" ! -name "*.js" ! -name "*.htaccess" '
#transforms a `find` exclusion pattern into a `find` inclusion pattern
# ' ! -name "*.jpg" ! -name "*.jpeg" ! -name "*.gif" ' ---> ' -a \( -name "*.jpg" -o -name "*.jpeg" -o -name "*.gif" \) '
# NB : there must exist a better (stateless) way to do that
local negativePattern_ # input for inverseNegPattern_()
local positivePattern_ # result of inverseNegPattern_()
inverseNegPattern_() {
if [[ "$OSflavor" =~ Darwin || "$OSflavor" =~ BSD ]]; then
positivePattern_=`echo $negativePattern_ | sed -E 's/^[[:space:]]*\!(.*)/ -a \\\( \1 \\\)/' | sed -E 's/\!/-o/g'`
else
positivePattern_=`echo $negativePattern_ | sed -r 's/^[[:space:]]*\!(.*)/ -a \\\( \1 \\\)/' | sed -r 's/\!/-o/g'`
fi
}
#HELP MESSAGE
usage()
{
echo -ne "
$EM${UN}usage:$UNQ$GR findall <options>$W$EMQ
${GR}This script searches for all (regular) files under the current directory
and its subdirectories, containing a specific string, with the exclusion
of any file nested in a $W.git$GR directory. 'directory' files are ignored too$W
$EM${UN}OPTIONS:$EMQ$UNQ
$R-h -? --help$B Show this message
$R--search=XXX$B String to search for in files
$R--type=YYY$B Pattern of the files to include in search ('*', '.*', '*.*', '*.js',...)
$EMB(you can't use --type with any of the 4 following options
$EMB--exclude --exclude-all --include --include-all)
$R--verbose -v$B verbose output : prints each matching line of each matching file
$R--nb=ZZZ$B ZZZ: integer
--> shows the query-matching lines of the ZZZth file from
the list generated without the --verbose option
$EMB(you can't use --nb= with --verbose)
$R--debug$B shows some additional debug info, and outputs a `find` pipe command
you can copy/paste which does what your findall command just did
$R--quiet$B returns 0 if no files were matched, returns 1 otherwise
NB: no other output (for use in 'if' statements)
$R--return-find-command$B returns the exact find command generated by the search
(also accessible via --debug); used by replaceall()
$W$EM${UN}EXCLUSIONS/INCLUSIONS:$UNQ ${GR} Options --include[-all] and --exclude[-all] are exclusive
of one another (and 'include' is more of a 'require'):
--exclude-all=script --include=rb will not turn out anything
--include-all=script --exclude=rb will remove 'rb' files from the
'${Y}script${GR}' ${Y}filter-group
$W$EMQ
$R--exclude$B filetypes to excluded : comma separated list of file extensions
to exclude. ex: --exclude=js,php,html
$R--exclude-all$B comma separated list of words amongst : ${Y}image,archive,script,html
$R--include$B filetypes to included : comma separated list of file extensions
to include. ex: --include=js,php,html
$EMB!: --include=js will ONLY match "*.js" files, so it's more of
a filter than an inclusion
$R--include-all$B comma separated list of words amongst : ${Y}image,archive,script,html
"
}
# COMMAND LINE ARGUMENTS
for i in $*
do
case $i in
--search=*)
string_=`echo $i | sed 's/[-a-zA-Z0-9]*=//'`
;;
--type=*)
pattern_=`echo $i | sed 's/[-a-zA-Z0-9]*=//'`
;;
--verbose | -v)
verbose_="v"
if [[ ! "$detail_" =~ ^$ ]]; then echo "can't use --verbose and --nb at the same time"; return 1; fi
;;
#-----------------------------------------------
# EXCLUSION is the easy part as it's associative
# just concatenate sequences of " ! -name 'pattern' " directly into $findCommand_2
--exclude=*)
exclude_=`echo $i | sed 's/[-a-zA-Z0-9]*=//'`
for i in $(echo $exclude_ | tr "," "\n"); do findCommand_2=$findCommand_2' ! -name "*.'$i'" '; done
;;
--exclude-all=*)
exclude_all_=`echo $i | sed 's/[-a-zA-Z0-9]*=//'`
for i in $(echo $exclude_all_ | tr "," "\n"); do
case $i in
# FEEL FREE to augment THESE !
image) findCommand_2=$findCommand_2$EXCL_f_image_ ;;
archive) findCommand_2=$findCommand_2$EXCL_f_archive_ ;;
script) findCommand_2=$findCommand_2$EXCL_f_script_ ;;
html) findCommand_2=$findCommand_2$EXCL_f_html_ ;;
*) echo "unknown param $i for option --exclude-all"; return 1 ;;
esac
done
;;
#-----------------------------------------------
# INCLUSION is more tricky
# we need to concatenate all inclusions in a
# '-a \( -name "pattern1" -o -name "pattern2" -o -name "pattern3" \)' group
# for the `find`command to process them nicely along --exclude and --exclude-all
# arguments.
# NB: entries from --include and --include-all must be included a single
# '-a \( ...\) group, finally added to $findCommand_2, see below
--include=*)
include_=`echo $i | sed 's/[-a-zA-Z0-9]*=//'`
# add to the negative pattern
for i in $(echo $include_ | tr "," "\n"); do negativePattern_=$negativePattern_' ! -name "*.'$i'" '; done
;;
--include-all=*)
include_all_=`echo $i | sed 's/[-a-zA-Z0-9]*=//'`
for i in $(echo $include_all_ | tr "," "\n"); do
positivePattern_=""
case $i in
# FEEL FREE to augment THESE !
image) negativePattern_=$negativePattern_$EXCL_f_image_ ;;
archive) negativePattern_=$negativePattern_$EXCL_f_archive_ ;;
script) negativePattern_=$negativePattern_$EXCL_f_script_ ;;
html) negativePattern_=$negativePattern_$EXCL_f_html_ ;;
*) echo "unknown param $i for option --exclude-all"; return 1 ;;
esac
done
;;
--nb=*)
detail_=`echo $i | sed 's/[-a-zA-Z0-9]*=//'`
if [[ ! "$verbose_" =~ ^$ ]]; then echo "can't use --verbose and --nb at the same time"; return 1; fi
;;
-h | -? | --help)
usage
return 0
;;
--debug)
debug_="1"
;;
--quiet)
quiet_=true
;;
--return-find-command)
rfc_=true
;;
*)
echo "unknown option $i" # unknown option
return 1
;;
esac
done
# finalize the $findCommand_2 in presence of --include or --include-all
if [[ ( ! "include_all_" =~ ^$ ) || ( ! "include_" =~ ^$ )]]; then
inverseNegPattern_
findCommand_2=$findCommand_2$positivePattern_
fi
# exit if searchstring is empty
if [[ "$string_" =~ ^$ ]]
then
echo -ne "\n$EMM...ERROR: no string to search for !\n\n$EMQ$W"
usage
return 1
fi
# replace empty pattern with "*"
if [[ "$pattern_" =~ ^$ ]]
then
pattern_="*"
[[ "$debug_" =~ 0 ]] || echo "${G}assuming --pattern=$pattern_"
fi
#SHORTCUT FUNCTIONS
# assemble the findCommand string
# which is of the form :
# find . -wholename './*.git' -prune -o -type f -name '$pattern_' ! -name "*.ext1" ! -name "*.ext2" (...) ! -name "*.extN" -print0
findCommand_=$findCommand_1$pattern_$findCommand_2$findCommand_3
debugFindCommand_=$findCommand_ # debug
findall_verbose() {
xargs -0 grep "$string_" -s | nl -s " ---> " | grep "$string_"
# xargs -0 grep "$string_" -s : find occurences of '$string' in each result of the (piped-in) `find` command, print all matching lines in all matching files
# and be quiet about error messages (-s)
# nl -s " ---> " : number the results with a special separator to distinguish this output from the synthetic one
# grep "$string_" : highlight our query string
}
findall_verbose_dbg() {
debugFindCommand_=$debugFindCommand_' | xargs -0 grep "'$string_'" -s | nl -s " ---> " | grep "'$string_'"'
}
findall_synthetic() {
xargs -0 grep "$string_" -sl | eval $sedSpace_ | xargs grep "$string_" -c | nl | grep :[0-9]*$
# xargs -0 grep "$string_" -sl : find occurences of '$string' in each result of the (piped-in) `find` command,
# but output the file path instead of each matched line of each file (-l), and be quiet about error messages (-s)
# ==> what it does : reduces the (piped-in) file list to the subset of files which contain '$string'
# eval $sedSpace_ : the filenames issued by the preceding command might contain whitespace --> we escape them for the next xargs
# NB : why not just use `xargs -0` next ? because then, the grep numbering of matched occurences (-c) doesn't occur
# and we only have a single-lined output passed to `nl`, so no numbering either in the final output
# xargs grep "$string_" -c : for each filename, outputs the filename followed by ":XX" where XX is the number of times '$string_' was found in the file
# nl : number the results
# grep :[0-9]*$ : highlight the ":XX" part in each result line for readability
}
findall_synthetic_dbg() {
debugFindCommand_=$debugFindCommand_' | xargs -0 grep "'$string_'" -sl | '$sedSpace_' | xargs grep "'$string_'" -c | nl | grep :[0-9]*$' # note that we removed the `eval`
}
findall_quiet() {
xargs -0 grep "$string_" -sl | eval $sedSpace_ | xargs grep "$string_" -c | wc -l
# xargs -0 grep "$string_" -sl : find occurences of '$string' in each result of the (piped-in) `find` command,
# but output the file path instead of each matched line of each file (-l), and be quiet about error messages (-s)
# ==> what it does : reduces the (piped-in) file list to the subset of files which contain '$string'
# eval $sedSpace_ : the filenames issued by the preceding command might contain whitespace --> we escape them for the next xargs
# NB : why not just use `xargs -0` next ? because then, the grep numbering of matched occurences (-c) doesn't occur
# and we only have a single-lined output passed to `nl`, so no numbering either in the final output
# xargs grep "$string_" -c : for each filename, outputs the filename followed by ":XX" where XX is the number of times '$string_' was found in the file
# nl : number the results
# grep :[0-9]*$ : highlight the ":XX" part in each result line for readability
}
findall_detail() {
xargs -0 grep "$string_" -sl | nl | grep -e '^[[:space:]]\+'$detail_'[[:space:]]\+' | eval $sedNumber_ | xargs -0 bash -c 'echo -ne "\n\n'$G$UN'INSPECT FILE:'$UNQ$EMM' $0\n\n'$NONE$W'"; cat "$(echo $0 | sed -e /^$/d)" | grep --color=auto "'$string_'"'
# xargs -0 grep "$string_" -sl : IDEM findall_synthetic
# nl : number the results
# grep -e '^[[:space:]]\+'$detail_'[[:space:]]\+' : retain the only line which matches the number '$detail_' (--nb=XX option)
# note : the + is escaped in `grep -e`
# eval $sedNumber : remove this number from the entry
# : ==> what it does : leaves us with one clean filepath (the one that matched --nb=XX)
# xargs -0 bash -c '(...)' : as we need to do several things on the (piped-in) filepath, we resort to invoking bash (-c : commandline) with xargs
# and then use the standard $0, $1... bash positional parameters to do things on the (piped-in) filepath
# nb:xargs -0 takes care of whitespaces in filepath
# echo -ne "'$G$UN'INSPECT FILE:'$UNQ$EMM' $0\n\n'$NONE$W'" : print a colored message with the filename
# cat "$(echo $0 | sed -e /^$/d)" : print the contents of the file on STDOUT
# ---> why not : cat $0 ? : cat "$0" would take care of spaces, but there's a trziling \n remaining from xargs
# ---> hence the $( echo $0 | sed ...)
# grep --color=auto "'$string_'" : and only retain those lines which match our query '$string'
}
findall_detail_dbg() {
debugFindCommand_=$debugFindCommand_" | xargs -0 grep \"$string_\" -sl | nl | grep -e '^[[:space:]]\+$detail_[[:space:]]\+' | $sedNumber_ | xargs -0 bash -c 'echo -ne \""
debugFindCommand_=$debugFindCommand_"\\\\n\\\\nINSPECT FILE: \$0\\\\n\\\\n\"; cat \"\$(echo \$0 | sed -e /^\$/d)\" | grep --color=auto \"$string_\"'"
}
#THE BIG PIPE
#--quiet
if [[ $rfc_ ]]
then echo $findCommand_
return 0
elif [[ $quiet_ ]]
then
local nboccurences_=`eval $findCommand_ | findall_quiet`
if [[ ! $nboccurences_ =~ 0 ]]; then return 0;
else return 1;
fi
#--verbose
elif [[ "$verbose_" =~ ^v$ ]]
then
log__=$EMY"\nVERBOSE:"$log__
eval $findCommand_ | findall_verbose
findall_verbose_dbg # debug
#no --verbose
elif [[ "$detail_" =~ ^$ ]]
then
log__=$EMY"\nSYNTHETIC:"$log__
eval $findCommand_ | findall_synthetic
findall_synthetic_dbg # debug
#detail
else
log__=$EMY"\nDETAIL:"$log__
eval $findCommand_ | findall_detail
findall_detail_dbg # debug
fi
log__=$EMY"\n-> finished search for all occurences of [$B$string_$EMY] in files of type [$B$pattern_$EMY]"
log__=$log__$EMY"\n-> Excluded file formats : $B$exclude_$EMY\n-> Excluded file groups : $B$exclude_all_$EMY"
log__=$log__$EMY"\n-> Included file formats : $B$include_$EMY\n-> Included file groups : $B$include_all_$EMY"
log__=$log__$EMY"\n-> FINDCOMMAND: $B$debugFindCommand_"
[[ "$debug_" =~ 0 || $quiet_ ]] || echo -ne $log__
return 0
}
# ---------------------------------------------------------------------------
# FIND & REPLACE in files
# This is the companion of the findall() command (relies on it)
# -> for security reasons, this function will only work inside a clean
# (commited) GIT repository so that undoing accidental changes is not a pb
# (just do a 'git reset --hard' to undo all changes)
function replaceall()
{
# test if findall exists
if ! findall -? >/dev/null 2>&1 ; then echo "ERROR: findall function is undefined"; return 1; fi
# *NIX sniffing
# reason : yeah, that again because 'sed -i' doesn't work the same on Darwin and Linux
if uname -s | grep "Darwin" >/dev/null 2>&1; then OSflavor="Darwin" # macos
fi
if uname -s | grep -E "FreeBSD|BSD\/OS" >/dev/null 2>&1; then OSflavor="BSD" # FreeBSD, BSD
fi
#CUSTOM COLORS : declare them as local variables so as not to clutter your BASH ENVIRONMENT
local NONE="\033[0m" # unsets color to term's fg color
local EM="\033[1m" #bold
local UN="\033[4m" #underline
local EMQ="\033[21m" #END bold
local UNQ="\033[24m" #END underline
local R="\033[0;31m" # red
local EMR="\033[1;31m" # bold red
local G="\033[0;32m" # green
local GR="\033[0;30m" # grey
local EMY="\033[1;33m" # bold yellow
local Y="\033[0;33m" # yellow
local B="\033[0;34m" # blue
local EMB="\033[1;34m" # bold blue
local EMM="\033[1;35m" # bold magenta
local C="\033[0;36m" # cyan
local W="\033[0;37m" # white
local args_=$# string_ replace_ pattern_ exclude_ exclude_all_ include_ include_all_
local log__
#########################################################################
# SECURITY
# This function has been restricted for use inside a GIT reository for
# security purposes. Feel free to delete this security test if you know
# what you're doing
#check git repo
if git rev-parse --git-dir >/dev/null 2>&1
then
log__=$log__$EMY"\n-> We're in a GIT repo : ok"
#check uncommited changes in repo
if git diff --quiet 2>/dev/null >&2
then
log__=$log__$EMY"\n-> the REPO is clean (all changes commited) : ok"
#uncommited changes in repo : FAIL
else
echo -ne "${C} ->${R} This GIT repository has some uncommited changes.\n Commit first before using replaceall()"
return 0
fi
#not a GIT repo : FAIL
else
echo -ne "${C} ->${R} Not a GIT repository.\n the FIND & REPLACE command is only available inside a GIT repository !"
return 0
fi
#########################################################################
#HELP MESSAGE
usage()
{
echo -ne "
$EM${UN}usage:$UNQ$GR findall <options>$W$EMQ
${GR}This script searches for all (regular) files under the current directory
and its subdirectories, containing a specific string, with the exclusion
of any file nested in a $W.git$GR directory. 'directory' files are ignored too$W
$EM${UN}OPTIONS:$EMQ$UNQ
$R-h -? --help$B Show this message
$R--search=XXX$B String to search for in files
$R--replace=YYY$EMR String to search for in files
$R--type=YYY$B Pattern of the files to include in search ('*', '.*', '*.*', '*.js',...)
$EMB(you can't use --type with any of the 4 following options
$EMB--exclude --exclude-all --include --include-all)
$W$EM${UN}EXCLUSIONS/INCLUSIONS:$UNQ ${GR} Options --include[-all] and --exclude[-all] are exclusive
of one another (and 'include' is more of a 'require'):
--exclude-all=script --include=rb will not turn out anything
--include-all=script --exclude=rb will remove 'rb' files from the
'${Y}script${GR}' ${Y}filter-group
$W$EMQ
$R--exclude$B filetypes to excluded : comma separated list of file extensions
to exclude. ex: --exclude=js,php,html
$R--exclude-all$B comma separated list of words amongst : ${Y}image,archive,script,html
$R--include$B filetypes to included : comma separated list of file extensions
to include. ex: --include=js,php,html
$EMB!: --include=js will ONLY match "*.js" files, so it's more of
a filter than an inclusion
$R--include-all$B comma separated list of words amongst : ${Y}image,archive,script,html
"
}
# COMMAND LINE ARGUMENTS
# we just parse them as all the file matching is passed to
# (delegated to) the findall() command
for i in $*
do
case $i in
--search=*) string_=`echo $i | sed 's/[-a-zA-Z0-9]*=//'` ;;
--replace=*) replace_=`echo $i | sed 's/[-a-zA-Z0-9]*=//'` ;;
--type=*) pattern_=`echo $i | sed 's/[-a-zA-Z0-9]*=//'` ;;
--exclude=*) exclude_=`echo $i | sed 's/[-a-zA-Z0-9]*=//'` ;;
--exclude-all=*) exclude_all_=`echo $i | sed 's/[-a-zA-Z0-9]*=//'` ;;
--include=*) include_=`echo $i | sed 's/[-a-zA-Z0-9]*=//'` ;;
--include-all=*) include_all_=`echo $i | sed 's/[-a-zA-Z0-9]*=//'` ;;
-h | -? | --help) usage; return 1 ;;
*) echo "unknown option $i"; return 1 ;;
esac
done
# exit if searchstring is empty
if [[ "$string_" =~ ^$ ]]
then
echo -ne "\n$EMM...ERROR: no string to search for !\n\n$EMQ$W"
usage
return 1
fi
# replace empty pattern with "*"
if [[ "$pattern_" =~ ^$ ]]
then
pattern_="*"
# [[ "$debug_" =~ 0 ]] || echo "${G}assuming --pattern=$pattern_"
fi
# ALERT message if replacement pattern is empty
if [[ "$replace_" =~ ^$ ]]
then
echo -ne "${C}->${Y} ALERT: matching pattern occurences will be replaced by EMPTY string\n"
fi
#perform a quiet search
if ! findall --search=$string_ --type=$pattern_ --include=$include_ --include-all=$include_all_ --exclude=$exclude_ --exclude-all=$exclude_all_ --quiet
then
echo -ne "${C} ->${R}the search didn't match any result\n... EXITING\n"
return 0
fi
#store the find command
local fc__=`findall --search=$string_ --type=$pattern_ --include=$include_ --include-all=$include_all_ --exclude=$exclude_ --exclude-all=$exclude_all_ --return-find-command`
#display the search results
echo -ne "\n\n${EMR}FILES WHICH WILL BE MODIFIED :\n$W"
findall --search=$string_ --type=$pattern_ --include=$include_ --include-all=$include_all_ --exclude=$exclude_ --exclude-all=$exclude_all_
#? confirm [y/n]
echo -ne "\n$EMR > Please confirm that you wish to replace ALL occurences in these files of string ${Y}[$EMM$string_$Y${Y}]${EMR} by string ${Y}[$EMM$replace_$Y]${EMR}, (y/n): "
read confirm_
if [[ "$confirm_" =~ ^y$ ]]
then
echo -ne "${C}->${Y} proceeding...\n"
else
echo -ne "${R}... ABORTED\n"
return 0
fi
#perform the replacement
if [[ "$OSflavor" =~ Darwin ]] # NOT checked on BSD!!
then
# MACOS (cf. http://alexle.net/archives/tag/invalid-command-code)
eval $fc__ | xargs -0 grep "$string_" -sl | sed -E 's/[[:space:]]+/\\ /g' | xargs sed -i "" "s/$string_/$replace_/g"
else
# LINUX
eval $fc__ | xargs -0 grep "$string_" -sl | sed -r 's/[[:space:]]+/\\ /g' | xargs sed -i "s/$string_/$replace_/g"
fi
echo -ne "\n${C}->${Y} All occurences replaced :)\n${G}...EXITING\n"
return 1;
}
@peterhost
Copy link
Author

I thought this would take me a few minutes, and it turned out to take a few hours. So I thought I might share my little findall.sh and replaceall.sh (to be added to your .bashrc).
I often have to move legagy php websites from one host to another, and find myself making (violent) batch 'string replacement' in whole /var/www directories containing thousands of files in order to transplant badly coded (ie tweaked cms-based) websites from one domain to another, in a matter of minutes. I use findall.sh for that.
findall --search=www.domain1.com --exclude-all=image,archive
(coz believe it or not, images store metadata)

Details of the nth entry :
findall --search=www.domain1.com --exclude-all=image,archive --nb=n
I use it in conjunction with replaceall.sh
replaceall --search=www.domain1.com --replace=www.domain2.com --exclude-all=image,archive

NB : tested on Darwin, Linux Debian, and a few other weird *nix distros

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment