将结果从一个命令传输到另一个命令时处理 bash 中的空格

将结果从一个命令传输到另一个命令时处理 bash 中的空格

我需要递归地遍历几个目录/文件,bash如果某个字符串存在于文件中,则将其替换为另一个字符串。我在脚本中用以下行解决了这个问题:

grep -rl "stringToReplace" * | xargs sed -ie 's/stringToReplace/newString/'

直到我看到有些文件的名称中含有空格。因此,如果有一个名为 的文件"dir1/dir2/I Am A File.txt",则xargs尝试向 sed 提供 4 个文件:"dir1/dir2/I""Am"和。"A""File.txt"

我已经尝试了一切我能想到的方法来解决这个问题,但还是不行。有人有主意吗?

答案1

grep | xargs不是处理此类事情的最佳工具,因为它无法安全地处理复杂的文件名。但是,如果您的文件名不包含换行符,您有几个选择:

grep -rl "stringToReplace" * | xargs -I {} sed -ie 's/stringToReplace/newString/' {}

这适用于任何 (XSI) POSIX 兼容xargs-I {}强制单行处理,并{}在参数中出现时将其替换为文件名。

通过 GNU grep 您可以使用:

grep -rl "stringToReplace" * | xargs -d '\n' sed -ie 's/stringToReplace/newString/'

这明确使用换行符而不是空格作为分隔符,但它是一个不可移植的扩展。

更安全地尊重任何可能的文件名,包括包含换行符的迟钝文件名,是这个POSIXfind命令:

find . -type f -exec grep -q "stringToReplace" {} \; -exec sed -ie 's/stringToReplace/newString/' {} +

它确实产生了很多greps - 第一个-exec对当前目录中找到的每个常规文件运行一次,第二个仅对第一个返回成功的文件组运行(即grep在文件中找到模式的位置)。对于您正在做的事情来说,额外的进程可能不是主要问题,但如果某些文件系统上有许多小文件,它们可能会占主导地位。

更安全,但不那么可移植,-execdirGNU 和 BSD 的主要版本find基本上会做同样的事情,但可以防止某些重命名攻击。

相关内容