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

This comment has been minimized.

Copy link

commented Sep 29, 2016

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

@graingert

This comment has been minimized.

Copy link

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

This comment has been minimized.

Copy link

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

This comment has been minimized.

Copy link

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

This comment has been minimized.

Copy link

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.

@NightMachinary

This comment has been minimized.

Copy link

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.
@NightMachinary

This comment has been minimized.

Copy link

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.