查找文本为“example.html”的所有文件,并替换为“example.php”,仅当文件名中没有空格时才有效

时间:2013-12-31 13:12:10

标签: bash unix sed grep xargs

我已经使用以下方法在文件中进行递归查找和替换,以更新hrefs以正确指向新页面:

#!/bin/bash
oldstring='features.html'
newstring='features.php'
grep -rl $oldstring public_html/ | xargs sed -i s@"$oldstring"@"$newstring"@g

除了一些名称中有空格的文件外,它有效。

这不是问题,因为名称中包含空格的文件是我在测试新内容时创建的备份/重复项。但是我想了解如何在此查询中将带空格的路径正确传递给sed命令。有人会知道如何在这个“单线”中纠正这个问题吗?

2 个答案:

答案 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视为其输入的参数分隔符,而不是在空格处断开输入。

实际上,您甚至不需要NULgrep,只需从xargs运行sed

find

答案 1 :(得分:1)

这是 lazy 方法:

grep -rl $oldstring public_html/ | xargs -d'\n' sed -i "s@$oldstring@$newstring@g"

默认情况下,xargs使用空格作为来自输入的参数的分隔符。例如,如果您有两个文件a bc,那么它将执行命令:

sed -i 's/.../.../' a b c

通过明确告诉xargs使用换行符作为-d '\n'的分隔符,它将正确处理a b作为单个参数,并在运行命令时引用它:

sed -i 's/.../.../' 'a b' c

我调用了 lazy 方法,因为正如@Barmar指出的那样,如果您的文件名称中包含换行符,则无效。如果您需要处理此类案件,请使用@ Barmar的方法find ... -print0xargs -0 ...

PS:我还将s@"$oldstring"@"$newstring"@g更改为"s@$oldstring@$newstring@g",这是等效的,但更具可读性。