我需要递归地遍历几个目录/文件,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/' {} +
它确实产生了很多grep
s - 第一个-exec
对当前目录中找到的每个常规文件运行一次,第二个仅对第一个返回成功的文件组运行(即grep
在文件中找到模式的位置)。对于您正在做的事情来说,额外的进程可能不是主要问题,但如果某些文件系统上有许多小文件,它们可能会占主导地位。
更安全,但不那么可移植,-execdir
GNU 和 BSD 的主要版本find
基本上会做同样的事情,但可以防止某些重命名攻击。