xargs is particularly useful when you have a list of filepaths on stdin and want to do something with them. For example:
$ git ls-files "*.tex" | xargs -n 1 sed -i "s/color/colour/g"
Let's examine this step by step:
$ git ls-files "*.tex"
tex/ch1/intro.tex
tex/ch1/motivation.tex
....
In other words, our input is a list of paths that we want to do something to.
To find out what xargs does with these paths, a nice trick is to add echo
before your command, like so:
$ git ls-files "*.tex" | xargs -n 1 echo sed -i "s/color/colour/g"
sed -i "s/color/colour/g" tex/ch1/intro.tex
sed -i "s/color/colour/g" tex/ch1/motivation.tex
....
The -n 1
argument will make xargs turn each line into a command of its own. The sed -i "s/color/colour/g"
command will replace all occurrences of color
with colour
for the specified file.
Note that this only works if you don't have any spaces in your paths. If you do, you should use null terminated paths as input to xargs by passing the -0
flag. An example usage would be:
$ git ls-files -z "*.tex" | xargs -0 -n 1 sed -i "s/color/colour/g"
Which does the same as what we described above, but also works if one of the paths has a space in it.
This works with any command that produces filenames as output such as find
or locate
. If you do happen to use it in a git repository with a lot of files though, it might be more efficient to use it with git grep -l
instead of git ls-files
, like so:
$ git grep -l "color" "*.tex" | xargs -n 1 sed -i "s/color/colour/g"
The git grep -l "color" "*.tex"
command will give a list of "*.tex" files containing the phrase "color".