Skip to content

Instantly share code, notes, and snippets.

@wayou
Last active October 26, 2018 03:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wayou/53cfe323f7ca35125ab24ebdf1e6e1f9 to your computer and use it in GitHub Desktop.
Save wayou/53cfe323f7ca35125ab24ebdf1e6e1f9 to your computer and use it in GitHub Desktop.
find and replace recursively for a directory using shell

Recursively find and replace with bash by leveraging the grep and sed command.

Syntax

grep -rlG <regexp pattern> <path> | xargs sed -i '' 's/pattern/replacement/g'

How it works

  1. grep

The G flag for grep enable regexp and l makes it print path only then used as input by sed.

  1. sed

NOTE: On Mac OS we need to assign an empty argument for -i flag, or if you wanna backup then using an none empty argument, e.g. -i "backup"

sed works as strem editor and s/pattern/replacement/g means replace pattern with repalcement. The pattern can be plain text or regexp.

NOTE: if you wanna match words within the sed pattern part, instead of using \w+, which doesn't work with sed, we need to use [a-z|A-Z]*.

Example

$ grep -rlE "\/foo\/bar\/\w*?\/" . | xargs sed -i "" "s/\/foo\/bar\/[a-z|A-Z]*\//\.\//g"

the result would be:

- import sth from '/foo/bar/baz/quz'
+ import sth from './quz'

Using variable within regexp

If the regexp are generated dynamically, that is to say, there's variable in the regexp pattern, note that we need to use double quotes.Single quotes prevent the shell variable from being interpolated by the shell.

e.g.:

arr=("foo" "bar")
for item in "${arr[@]}"
do
  grep -rlE "\/src\/$item\/\w*?\/" . | xargs sed -i "" "s/\/src\/$item\/[a-z|A-Z]*\//\.\//g"
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment