我已经使用以下方法在文件中进行递归查找和替换,以更新hrefs以正确指向新页面:
#!/bin/bash
oldstring='features.html'
newstring='features.php'
grep -rl $oldstring public_html/ | xargs sed -i s@"$oldstring"@"$newstring"@g
除了一些名称中有空格的文件外,它有效。
这不是问题,因为名称中包含空格的文件是我在测试新内容时创建的备份/重复项。但是我想了解如何在此查询中将带空格的路径正确传递给sed命令。有人会知道如何在这个“单线”中纠正这个问题吗?
答案 0 :(得分:4)
find public_html/ -type f -exec grep -q "$oldstring" {} \; -print0 |
xargs -0 sed -i '' s@"$oldstring"@"$newstring"@g
find
将打印grep
命令成功的所有文件名。我使用-print0
选项以NUL
字符作为分隔符打印它们。这与-0
的{{1}}选项一致,它将xargs
视为其输入的参数分隔符,而不是在空格处断开输入。
实际上,您甚至不需要NUL
和grep
,只需从xargs
运行sed
:
find
答案 1 :(得分:1)
这是 lazy 方法:
grep -rl $oldstring public_html/ | xargs -d'\n' sed -i "s@$oldstring@$newstring@g"
默认情况下,xargs
使用空格作为来自输入的参数的分隔符。例如,如果您有两个文件a b
和c
,那么它将执行命令:
sed -i 's/.../.../' a b c
通过明确告诉xargs
使用换行符作为-d '\n'
的分隔符,它将正确处理a b
作为单个参数,并在运行命令时引用它:
sed -i 's/.../.../' 'a b' c
我调用了 lazy 方法,因为正如@Barmar指出的那样,如果您的文件名称中包含换行符,则无效。如果您需要处理此类案件,请使用@ Barmar的方法find ... -print0
和xargs -0 ...
PS:我还将s@"$oldstring"@"$newstring"@g
更改为"s@$oldstring@$newstring@g"
,这是等效的,但更具可读性。