sed to replace string in file only displayed but not executed

Viewed 56

I want to find all files with certain name (Myfile.txt) that do not contain certain string (my-wished-string) and then do a sed in order to do a replace in the found files. I tried with:

find . -type f -name "Myfile.txt" -exec grep -H -E -L "my-wished-string" {} + | sed 's/similar-to-my-wished-string/my-wished-string/'

But this only displays me all files with wished name that miss the "my-wished-string", but does not execute the replacement. Do I miss here something?

3 Answers

With a for loop and invoking a shell.

find . -type f -name "Myfile.txt" -exec sh -c '
  for f; do
    grep -H -E -L "my-wished-string" "$f" &&
    sed -i "s/similar-to-my-wished-string/my-wished-string/" "$f"
done' sh {} +

You might want to add a -q to grep and -n to sed to silence the printing/output to stdout

You can do this by constructing two stacks; the first containing the files to search, and the second containing negative hits, which will then be iterated over to perform the replacement.

find . -type f -name "Myfile.txt" > stack1
while read -r line;
do
[ -z $(sed -n '/my-wished-string/p' "${line}") ] && echo "${line}" >> stack2
done < stack1

while read -r line;
do
sed -i "s/similar-to-my-wished-string/my-wished-string/" "${line}"
done < stack2

With some versions of sed, you can use -i to edit the file. But don't pipe the list of names to sed, just execute sed in the find:

find . -type f -name Myfile.txt -not -exec grep -q "my-wished-string" {} \; -exec sed -i 's/similar-to-my-wished-string/my-wished-string/g' {} \;

Note that any file which contains similar-to-my-wished-string also contains the string my-wished-string as a substring, so with these exact strings the command is a no-op, but I suppose your actual strings are different than these.

Related