我如何查找并替换每次出现的:
subdomainA.example.com
具有
subdomainB.example.com
递归地在/home/www/目录树下的每个文本文件中?
我如何查找并替换每次出现的:
subdomainA.example.com
具有
subdomainB.example.com
递归地在/home/www/目录树下的每个文本文件中?
当前回答
如果您需要排除目录(--exclude-dir=..folder),并且文件名可能带有空格(通过对grep-Z和xargs-0使用0Byte来解决),这是一种直接的方法
grep -rlZ oldtext . --exclude-dir=.folder | xargs -0 sed -i 's/oldtext/newtext/g'
其他回答
这是我为OSX和Windows(msys2)找到的最好的全方位解决方案。应该可以使用任何可以获得gnu版本sed的东西。跳过.git目录,这样不会损坏您的校验和。
在mac上,只需先安装coreutils并确保gsed在路径中-
brew install coreutils
然后我将此函数粘贴到zshrc/bashrc->
replace-recursive() {
hash gsed 2>/dev/null && local SED_CMD="gsed" || SED_CMD="sed"
find . -type f -name "*.*" -not -path "*/.git/*" -print0 | xargs -0 $SED_CMD -i "s/$1/$2/g"
}
usage: replace-recursive <find> <replace>
find /home/www/ -type f -exec perl -i.bak -pe 's/subdomainA\.example\.com/subdomainB.example.com/g' {} +
find/home/www/-type f将列出/home/ww/(及其子目录)中的所有文件。“-exec”标志告诉find对找到的每个文件运行以下命令。
perl -i.bak -pe 's/subdomainA\.example\.com/subdomainB.example.com/g' {} +
是在文件上运行的命令(一次运行多个)。{}被文件名替换。告诉find为多个文件名构建一个命令。
根据查找手册页:“命令行的构建方式与xargs构建其命令行。"
因此,不使用xargs-0或-print0就可以实现目标(并处理包含空格的文件名)。
我很惊讶我没有看到使用文件globbing的简单答案,我只使用**/package.json扫描/更新package.json文件
这是zsh下macos特有的
cd /home/www
sed -i '' -e 's/subdomainA.example.com/subdomainA.example.com/g' **/*
find /home/www \( -type d -name .git -prune \) -o -type f -print0 | xargs -0 sed -i 's/subdomainA\.example\.com/subdomainB.example.com/g'
-print0告诉find打印由空字符分隔的每个结果,而不是新行。如果您的目录中包含名称中带有换行符的文件,这是不太可能的,那么xargs仍然可以使用正确的文件名。
\(-type d-name.git-prenne\)是一个表达式,它完全跳过名为.git的所有目录。如果您使用SVN或有其他要保留的文件夹,则可以轻松展开它,只需匹配更多名称即可。它大致相当于-not-path.git,但效率更高,因为它不检查目录中的每个文件,而是完全跳过它。后面的-o是必需的,因为-prime实际上是如何工作的。
有关更多信息,请参阅man find。
要减少要递归遍历的文件,可以对字符串实例进行grep:
grep -rl <oldstring> /path/to/folder | xargs sed -i s^<oldstring>^<newstring>^g
如果运行man grep,您会注意到,如果您想省略对.git目录的搜索,还可以定义一个--exlude dir=“*.git”标志,从而避免了其他人礼貌地指出的git索引问题。
引导您:
grep -rl --exclude-dir="*.git" <oldstring> /path/to/folder | xargs sed -i s^<oldstring>^<newstring>^g