I have used the following to do a recursive find and replace within files, to update hrefs to point to a new page correctly:
#!/bin/bash
oldstring='features.html'
newstring='features.php'
grep -rl $oldstring public_html/ | xargs sed -i s@"$oldstring"@"$newstring"@g
It worked, except for a few files that had spaces in the name.
This isn't an issue, as the files with spaces in their names are backups/duplicates I created while testing new things. But I'd like to understand how I could properly pass paths with spaces to the sed command, in this query. Would anybody know how this could be corrected in this "one liner"?
find public_html/ -type f -exec grep -q "$oldstring" {} \; -print0 |
xargs -0 sed -i '' s@"$oldstring"@"$newstring"@g
find
will print all the filenames for which the grep
command is successful. I use the -print0
option to print them with the NUL
character as the delimiter. This goes with the -0
option to xargs
, which treats NUL
as the argument delimiter on its input, rather than breaking the input at whitespace.
Actually, you don't even need grep
and xargs
, just run sed
from find
:
find public_html/ -type f -exec sed -i '' s@"$oldstring"@"$newstring"@g {} +
Here's a lazy approach:
grep -rl $oldstring public_html/ | xargs -d'\n' sed -i "s@$oldstring@$newstring@g"
By default, xargs
uses whitespace as the delimiter of arguments coming from the input. So for example if you have two files, a b
and c
, then it will execute the command:
sed -i 's/.../.../' a b c
By telling xargs
explicitly to use newline as the delimiter with -d '\n'
it will correctly handle a b
as a single argument and quote it when running the command:
sed -i 's/.../.../' 'a b' c
I called a lazy approach, because as @Barmar pointed out, this won't work if your files have newline characters in their names. If you need to take care of such cases, then use @Barmar's method with find ... -print0
and xargs -0 ...
PS: I also changed s@"$oldstring"@"$newstring"@g
to "s@$oldstring@$newstring@g"
, which is equivalent, but more readable.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With