我需要替换一个文件夹中的许多文件中的字符串,只有ssh访问服务器。我该怎么做呢?


当前回答

真的很蹩脚,但我不能让任何sed命令在OSX上工作,所以我做了这个愚蠢的事情:

:%s/foo/bar/g
:wn

^-复制这三行到我的剪贴板(是的,包括结束换行),然后:

vi *

按住command-v,直到它显示没有文件了。

愚蠢的…出租汽车司机…有效…

其他回答

如果文件包含反斜杠(通常是路径),你可以尝试这样做:

sed -i -- 's,<path1>,<path2>,g' *

ex:

sed -i -- 's,/foo/bar,/new/foo/bar,g' *.sh (in all shell scripts available)

有一个更简单的方法,使用一个简单的脚本文件:

   # sudo chmod +x /bin/replace_string_files_present_dir

在gedit或你选择的编辑器中打开文件,我在这里使用gedit。

   # sudo gedit /bin/replace_string_files_present_dir

然后在编辑器中将以下内容粘贴到文件中

   #!/bin/bash
   replace "oldstring" "newstring" -- *
   replace "oldstring1" "newstring2" -- *
   #add as many lines of replace as there are your strings to be replaced for 
   #example here i have two sets of strings to replace which are oldstring and 
   #oldstring1 so I use two replace lines.

保存文件,关闭gedit,然后退出您的终端,或者只是关闭它,然后启动它,以便能够加载您添加的新脚本。

导航到有多个要编辑的文件的目录。然后运行:

  #replace_string_files_present_dir

按enter键,这将自动将包含它们的所有文件中的oldstring和oldstring1分别替换为正确的newstring和newstring1。

它将跳过不包含旧字符串的所有目录和文件。

如果您有多个目录的文件需要替换字符串,这可能有助于消除乏味的输入工作。你所要做的就是导航到这些目录,然后运行:

# replace_string_files_present_dir

你所要做的就是确保你已经包括或添加了所有替换字符串,就像我上面展示的那样:

替换 “oldstring” “newstring” -- *

在文件/bin/replace_string_files_present_dir的末尾。

要添加一个新的替换字符串,只需打开我们创建的脚本,在终端中输入以下命令:

Sudo gedit /bin/replace_string_files_present_dir

不要担心你添加的替换字符串的数量,如果没有找到oldstring,它们将没有任何影响。

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
cd /path/to/your/folder
sed -i 's/foo/bar/g' *

出现的“foo”将被替换为“bar”。

在像macOS这样的BSD系统上,你需要提供一个备份扩展名,比如-i '.bak',否则每个manpage都会“冒损坏或部分内容的风险”。

cd /path/to/your/folder
sed -i '.bak' 's/foo/bar/g' *

我对许多答案的问题是,我需要替换许多文件中的文件路径。虽然有一个答案提到了这一点,但对我来说并不管用。我的解决方案:

首先,生成一个要更改的文件名列表。

filelist=($(find /path/to/your/folder | xargs grep '/path/to/fix' | cut -d : -f 1 | tr '\n' ' '))

上面的命令所做的是,管道到grep的find生成包含/路径/到/fix的文件名。然而,grep也打印出字符串所在的行,所以cut命令去掉了这个,只保留文件名。Tr将换行符替换为空格,允许将文件列表存储为数组。

for file in "${filelist[@]}"; do sed -i.bak 's+/path/to/fix+/new/path/for/my/file+g' $file; done

这个sed命令利用了这个问题的其他答案,并使用+作为分隔符而不是普通的/,因为文件路径中使用了/字符。