This question already has an answer here:

I'm trying to pass a list of files with a known set of characters to sed for a find and replace.

For a directory containing multiple .xml files:

ls -la


Each containing a matching string:

grep -i foo *

file1.xml <foo/>
file2.xml <foo/>
file3.xml <foo/>

Replace foo with bar using a for loop:

for f in *.xml; do ls | sed -i "s|foo|bar|g" ; done


sed: no input files
sed: no input files
sed: no input files

I already figured out an alternative that works, so this is mostly for my own edification at this point.

find /dir/ -name '*.xml' -exec sed -i "s|foo|bar|g" {} \;

marked as duplicate by don_crissti, Stephen Rauch, Rui F Ribeiro, Jeff Schaller, Anthon Jul 5 '17 at 19:42

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.


You have a flaw in your for loop. Remove the ls command, and add the $f variable as the argument to sed -i, which will edit each filename.xml in place:

for f in *.xml; do sed -i "s|foo|bar|g" "$f"; done
  • 1
    Bingo. This is what I was aiming for. – Bert Jul 5 '17 at 18:57

Note that in the GNU sed you can edit multiple files and in-place as well. So your task thus reduces to:

sed -i -se 's|foo|bar|g' *.xml

-s for --separate is the sed option that does it.


sed is expecting the input path as a parameter. So try a construction as the following:

 … | sed -i "…" /dev/stdin

It would be even easier to use the files as parameter, as this (untested):

sed -i "..." *.xml

Not the answer you're looking for? Browse other questions tagged or ask your own question.