1

I want to replace all str1 strings in files in the current directory with str2. I use

sed -i s/str1/str2/g `grep str1 -rl   ./`

command or

sed -i s/str1/str2/g `grep str1 -rl --include="*.*"  ./`

There is an error that the parameter is too long. Can someone tell me why? I googled this command. I also read the introduction of sed and grep, and I feel that there are no errors.

Yujie
  • 193

1 Answers1

2

grep str1 -rl . generates the list of all files that contain str1. That list is simply too long. This is not a problem of sed or grep, but the amount of space your system provides to parameters. A discussion of the "argument list too long" error can be found on this same forum.

One way of fixing that is with xargs:

grep -rl str1 . | xargs sed -i 's/str1/str2/'

xargs takes its input and calls sed repeatedly with appropriately sized portions of the entire input.

Since we don't know if there are weird filenames that contain special characters like spaces, ";", "|" and the like, a better way might be

find . -type f -exec sed -i 's/str1/str2/' {} \;

find goes through all regular files and performs the substitution if the file contains str1. Calling grep to check if the file does contain str1 is wasteful.

Note that these solutions, like your original question, assume that all files can be processed with sed, i.e. they are text files. If you are not sure about that, this code only runs sed after confirming that the file is a text file:

find . -type f -exec sh -c "file {} | grep -q text && sed -i 's/str1/str2/' {}" \;
berndbausch
  • 3,557