如何在linux命令行中replace多个文件中的string
我需要replace文件夹中的许多文件中的string,只有ssh
访问服务器。 我怎样才能做到这一点?
cd /path/to/your/folder sed -i 's/foo/bar/g' *
“foo”的发生将被replace为“bar”。
类似于Kaspar的答案,但用g标志来replace一行中的所有事件。
find ./ -type f -exec sed -i 's/string1/string2/g' {} \;
对于全局不区分大小写:
find ./ -type f -exec sed -i 's/string1/string2/gI' {} \;
@ kev的答案是好的,但只影响直接目录中的文件。下面的例子使用greprecursion查找文件。 它每次都适合我
grep -rli 'old-word' * | xargs -i@ sed -i 's/old-word/new-word/g' @
这对我工作:
find ./ -type f -exec sed -i 's/string1/string2/' {} \;
Howerver,这没有: sed -i 's/string1/string2/g' *
。 也许“富”不是为了string1和“酒吧”不是string2。
要replace多个文件中的string,您可以使用:
grep -rl matchstring somedir/ | xargs sed -i 's/string1/string2/g'
例如
grep -rl 'windows' ./ | xargs sed -i 's/windows/linux/g'
来源博客
有一些标准答案已经列出。 通常,您可以使用findrecursion列出文件,然后使用sed或perl执行操作。
对于大多数快速使用,您可能会发现命令rpl更容易记住。 这里是replace(富 – >酒吧),recursion的所有文件:
rpl -R foo bar .
你可能需要安装它( apt-get install rpl
或类似的)。
但是,对于涉及正则expression式和后置replace,文件重命名以及searchreplace的更复杂的工作 ,我所知道的最通用和最强大的工具是repren ,一个我为某些人编写的小Python脚本更棘手的重命名和重构任务。 你可能更喜欢它的原因是:
- 支持重命名文件以及search和replace文件内容。
- 在承诺执行search和replace之前查看更改。
- 支持正则expression式replace,全字,不区分大小写,保留大小写(replacefoo – > bar,Foo – > Bar,FOO – > BAR)模式。
- 可以使用多个replace,包括掉换(foo – > bar和bar – > foo)或一组非唯一replace(foo – > bar,f – > x)。
要使用它, pip install repren
。 检查自述文件的例子。
要replace文件中的path(避免转义字符),可以使用以下命令:
sed -i 's@old_path@new_path@g'
@符号表示所有的特殊字符都应该在下面的string中被忽略。
如果您有可以使用的文件列表
replace "old_string" "new_string" -- file_name1 file_name2 file_name3
在我发现这个问题之前,我做了自己的解决scheme(和答案)。 我search了“replace”“几个”和“xml”的不同组合,因为这是我的应用程序,但没有find这个特定的组合。
我的问题:我有春季XML文件与testing用例的数据,包含复杂的对象。 java源代码的重构改变了很多类,并不适用于xml数据文件。 为了保存testing用例数据,我需要更改所有xml文件中的所有类名,分布在多个目录中。 所有的同时保存原始xml文件的备份副本(尽pipe这不是必须的,因为版本控制可以将我保存在这里)。
我正在寻找find
+ sed
一些组合,因为它在其他情况下适用于我,但不能同时进行多个replace。
然后我发现问ubuntu的响应 ,它帮助我build立我的命令行:
find -name "*.xml" -exec sed -s --in-place=.bak -e 's/firstWord/newFirstWord/g;s/secondWord/newSecondWord/g;s/thirdWord/newThirdWord/g' {} \;
它的工作完美(好吧,我的情况有六个不同的替代品)。 但请注意,它会触及当前目录下的所有* .xml文件。 因此,如果你对版本控制系统负责,你可能需要首先进行筛选,然后只传递给那些实际上有你想要的string的sed
; 喜欢:
find -name "*.xml" -exec grep -e "firstWord" -e "secondWord" -e "thirdWord" {} \; -exec sed -s --in-place=.bak -e 's/firstWord/newFirstWord/g;s/secondWord/newSecondWord/g;s/thirdWord/newThirdWord/g' {} \;
grep --include={*.php,*.html} -rnl './' -e "old" | xargs -i@ sed -i 's/old/new/g' @
脚本为multiedit命令
multiedit [-n PATTERN] OLDSTRING NEWSTRING
从Kaspar的答案,我做了一个bash脚本接受命令行参数,并可选地限制匹配模式的文件名。 保存在你的$ PATH中,然后生成可执行文件,然后使用上面的命令。
这是脚本:
#!/bin/bash _help="\n Replace OLDSTRING with NEWSTRING recursively starting from current directory\n multiedit [-n PATTERN] OLDSTRING NEWSTRING\n [-n PATTERN] option limits to filenames matching PATTERN\n Note: backslash escape special characters\n Note: enclose STRINGS with spaces in double quotes\n Example to limit the edit to python files:\n multiedit -n \*.py \"OLD STRING\" NEWSTRING\n" # ensure correct number of arguments, otherwise display help... if [ $# -lt 2 ] || [ $# -gt 4 ]; then echo -e $_help ; exit ; fi if [ $1 == "-n" ]; then # if -n option is given: # replace OLDSTRING with NEWSTRING recursively in files matching PATTERN find ./ -type f -name "$2" -exec sed -i "s/$3/$4/g" {} \; else # replace OLDSTRING with NEWSTRING recursively in all files find ./ -type f -exec sed -i "s/$1/$2/" {} \; fi
“你也可以使用find和sed,但是我发现这个perl的这一行很好地工作。
perl -pi -w -e 's/search/replace/g;' *.php
- -e表示执行下面的代码行。
- -i表示就地编辑
- -w写警告
- -p循环
“(摘自http://www.liamdelahunty.com/tips/linux_search_and_replace_multiple_files.php )
我最好的结果来自使用perl和grep(以确保文件具有searchexpression式)
perl -pi -w -e 's/search/replace/g;' $( grep -rl 'search' )
如果文件包含反斜杠(通常是path),可以尝试如下所示:
sed -i -- 's,<path1>,<path2>,g' *
例如:
sed -i -- 's,/foo/bar,/new/foo/bar,g' *.sh (in all shell scripts available)
“foo”的第一行将被replace为“bar”。 你可以使用第二行来检查。
grep -rl 'foo' . | xargs sed -i 's/foo/bar/g' grep 'foo' -r * | awk -F: {'print $1'} | sort -n | uniq -c
你可以看到我写这篇文章: http : //jiasir.io/Replace-strings-with-sed-in-directory-and-sub-directories/
真的很蹩脚,但是我不能让任何sed命令在OSX上正常工作,所以我做了这个愚蠢的事情:
:%s/foo/bar/g :wn
^ – 复制这三行到我的剪贴板(是的,包括结束换行符),然后:
vi *
并按住command-v直到它说没有剩下的文件。
阿呆… …哈克有效…
当使用-i
开关调用stream编辑器时,stream编辑器会修改多个“inplace”文件,这会使备份文件以参数结尾。 所以
sed -i.bak 's/foo/bar/g' *
在此文件夹中的所有文件中用bar
replacefoo
,但不下降到子文件夹中。 这将为您的目录中的每个文件生成一个新的.bak
文件。 要recursion执行此目录及其所有子目录中的所有文件,需要使用助手(如find
)来遍历目录树。
find ./ -print0 | xargs -0 sed -i.bak 's/foo/bar/g' *
find
可以通过指定更多的参数,如find ./ -name '*.php' -or -name '*.html' -print0
,进一步限制要修改的文件。
注意:GNU sed
不需要文件结尾, sed -i 's/foo/bar/g' *
也能工作。 FreeBSD的sed
需要一个扩展名,但是允许两者之间有空格,所以sed -i .bak s/foo/bar/g *
可以工作。
可以使用下面的命令首先search文件并replace文件
找 。 | xargs grepsearchstring| sed's /searchstring/新string/ g'
如find。 | xargs grep abc | sed's / abc / xyz / g'
为了维护我的个人英语节点,我编写了一个实用程序脚本,用于recursion地replace目录下的所有文件,以replace多对旧/新string。
多对旧/新string在哈希映射中进行pipe理。
dir可以通过命令行或环境variables来设置,映射在脚本中是硬编码的,但是如果需要的话,你可以修改从文件加载的代码。
它需要bash 4.2,由于一些新的function。
en_standardize.sh:
#! /bin/bash # (need bash 4.2+,) # # Standardize phonetic symbol of English. # # format: # en_standardize.sh [<dir>] # # params: # * dir # target dir, optional, # if not specified then use environment variable "$node_dir_en", # if both not provided, then will not execute, # * # paramCount=$# # figure target dir, if [ $paramCount -ge 1 ]; then # dir specified echo -e "dir specified (in command):\n\t$1\n" targetDir=$1 elif [[ -v node_dir_en ]]; then # environable set, echo -e "dir specified (in environment vairable):\n\t$node_dir_en\n" targetDir=$node_dir_en else # environable not set, echo "dir not specified, won't execute" exit fi # check whether dir exists, if [ -d $targetDir ]; then cd $targetDir else echo -e "invalid dir location:\n\t$targetDir\n" exit fi # initial map, declare -A itemMap itemMap=( ["ɪ"]="i" ["ː"]=":" ["ɜ"]="ə" ["ɒ"]="ɔ" ["ʊ"]="u" ["ɛ"]="e") # print item maps, echo 'maps:' for key in "${!itemMap[@]}"; do echo -e "\t$key\t->\t${itemMap[$key]}" done echo -e '\n' # do replace, for key in "${!itemMap[@]}"; do grep -rli "$key" * | xargs -i@ sed -i "s/$key/${itemMap[$key]}/g" @ done echo -e "\nDone." exit
我正在给一个例子来修复python源代码中的一个常见的shebang错误。
您可以尝试grep / sed方法。 这是一个与GNU sed一起工作,不会破坏git回购:
$ grep -rli --exclude '*.git*' '#!/usr/bin/python' . | xargs -I {} \ gsed -i '' -e 's/#!\/usr\/bin\/python/#!\/usr\/bin\/env python/' {}
或者你可以使用greptile 🙂
$ greptile -x .py -l -i -g '#!/usr/bin/env python' -r '#!/usr/bin/python' .
我刚刚testing了第一个脚本,第二个脚本也是如此。 小心转义字符,我认为在大多数情况下应该更容易使用greptile。 当然,你可以用sed做很多有趣的事情,为此,最好把它和xargs一起使用。
我发现这个从另一个post(不记得哪一个),而不是最优雅的,这是简单的,作为一个新手Linux用户给了我没有麻烦
for i in *old_str* ; do mv -v "$i" "${i/\old_str/new_str}" ; done
如果您有空格或其他特殊字符,请使用\
for i in *old_str\ * ; do mv -v "$i" "${i/\old_str\ /new_str}" ; done
对于子目录中的string使用**
for i in *\*old_str\ * ; do mv -v "$i" "${i/\old_str\ /new_str}" ; done
$replace“从”“到” – “find / path / to / folder -type f”
(replace – MySQL数据库系统的stringreplace工具)