Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Bulk search & replace with ag (the_silver_searcher)
# ag <https://github.com/ggreer/the_silver_searcher>
# usage: ag-replace.sh [search] [replace]
# caveats: will choke if either arguments contain a forward slash
# notes: will back up changed files to *.bak files
ag -0 -l $1 | xargs -0 perl -pi.bak -e "s/$1/$2/g"
# or if you prefer sed's regex syntax:
ag -0 -l $1 | xargs -0 sed -ri.bak -e "s/$1/$2/g"
@dennislysenko
Copy link

dennislysenko commented Sep 29, 2016

If you add -0 right after xargs, it can also handle files with spaces in the filename ;)

@graingert
Copy link

graingert commented May 5, 2017

@dennislysenko you need the -0 in both ag and xargs

ag -0 -l $1 | xargs -0 sed -ri.bak -e "s/$1/$2/g"

@aaronmswan
Copy link

aaronmswan commented May 2, 2018

For what it's worth, this can be added as a function to .bashrc as

function agr { ag -0 -l "$1" | xargs -0 perl -pi.bak -e "s/$1/$2/g"; }
export -f agr

@KevOrr
Copy link

KevOrr commented May 3, 2018

Even better so you don't have to worry about slashes:

function agr { ag -0 -l "$1" | AGR_FROM="$1" AGR_TO="$2" xargs -r0 perl -pi -e 's/$ENV{AGR_FROM}/$ENV{AGR_TO}/g'; }

There could be some incompatibilities between the two regex languages though.

@ixis-kyle
Copy link

ixis-kyle commented May 2, 2019

@KevOrr,
function agr { ag -0 -l "$1" | AGR_FROM="$1" AGR_TO="$2" xargs -r0 perl -pi -e 's/$ENV{AGR_FROM}/$ENV{AGR_TO}/g'; } has typo. Should be:
function agr { ag -0 -l "$1" | AGR_FROM="$1" AGR_TO="$2" xargs -0 perl -pi -e 's/$ENV{AGR_FROM}/$ENV{AGR_TO}/g'; }.

at least thats what worked for me, I honestly dont know much about the -0 argument.

@NightMachinery
Copy link

NightMachinery commented Jul 29, 2019

@ixis-kyle It’s correct, and necessary:

-r, --no-run-if-empty
              If  the  standard input does not contain any nonblanks,
              do not run the command.  Normally, the command  is  run
              once  even  if there is no input.  This option is a GNU
              extension.

@NightMachinery
Copy link

NightMachinery commented Jul 29, 2019

(See latest version https://gist.github.com/NightMachinary/719ec06299c65b5216d551658b78c951)

comment() { 
}
doc() { 
}
function agr { 
doc 'usage: from=sth to=another agr [ag-args]'
comment -l --files-with-matches

ag -0 -l "$from" "${@}" | pre-files "$from" "$to"
}
pre-files() {
doc 'stdin should be null-separated list of files that need replacement; $1 the string to replace, $2 the replacement.'
comment '-i backs up original input files with the supplied extension (leave empty for no backup; needed for in-place replacement.)(do not put whitespace between -i and its arg.)'
comment '-r, --no-run-if-empty
              If  the  standard input does not contain any nonblanks,
              do not run the command.  Normally, the command  is  run
              once  even  if there is no input.  This option is a GNU
              extension.'

AGR_FROM="$1" AGR_TO="$2" xargs -r0 perl -pi.pbak -e 's/$ENV{AGR_FROM}/$ENV{AGR_TO}/g'
}

You can use it like this:

from=str1 to=sth agr path1 path2 ...

Supply no paths to make it use the current directory.
Note that ag, xargs, and perl need to be installed and on PATH.

@nikisix
Copy link

nikisix commented Apr 17, 2020

I had to use ag's --nocolor argument for it go work

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