How to replace a string in multiple files in linux

2019-01-07 01:49发布

I need to replace a string in a lot of files in a folder, with only ssh access to the server. How can I do this?

标签: linux string
22条回答
Fickle 薄情
2楼-- · 2019-01-07 01:52

This worked for me:

find ./ -type f -exec sed -i 's/string1/string2/' {} \;

Howerver, this did not: sed -i 's/string1/string2/g' *. Maybe "foo" was not meant to be string1 and "bar" not string2.

查看更多
霸刀☆藐视天下
3楼-- · 2019-01-07 01:52
grep --include={*.php,*.html} -rnl './' -e "old" | xargs -i@ sed -i 's/old/new/g' @
查看更多
叛逆
4楼-- · 2019-01-07 01:52

I am giving an example for fixing a common shebang error in python sources.

You can try the grep/sed approach. Here is one that works with GNU sed and won't break a git repo:

$ grep -rli --exclude '*.git*' '#!/usr/bin/python' . | xargs -I {} \
gsed -i '' -e 's/#!\/usr\/bin\/python/#!\/usr\/bin\/env python/' {}

Or you can use greptile :)

$ greptile -x .py -l -i -g '#!/usr/bin/env python' -r '#!/usr/bin/python' .

I just tested the first script, and the second should work as well. Be careful with escape characters, I think it should be easier to use greptile in most cases. Of course, you can do many interesting things with sed, and for that it may be preferable to master using it with xargs.

查看更多
我只想做你的唯一
5楼-- · 2019-01-07 01:53

The stream editor does modify multiple files “inplace” when invoked with the -i switch, which takes a backup file ending as argument. So

sed -i.bak 's/foo/bar/g' *

replaces foo with bar in all files in this folder, but does not descend into subfolders. This will however generate a new .bak file for every file in your directory. To do this recursively for all files in this directory and all its subdirectories, you need a helper, like find, to traverse the directory tree.

find ./ -print0 | xargs -0 sed -i.bak 's/foo/bar/g' *

find allows you further restrictions on what files to modify, by specifying further arguments like find ./ -name '*.php' -or -name '*.html' -print0, if necessary.


Note: GNU sed does not require a file ending, sed -i 's/foo/bar/g' * will work, as well; FreeBSD sed demands an extension, but allows a space in between, so sed -i .bak s/foo/bar/g * works.

查看更多
萌系小妹纸
6楼-- · 2019-01-07 01:57

script for multiedit command

multiedit [-n PATTERN] OLDSTRING NEWSTRING

From Kaspar's answer I made a bash script to accept command line arguments and optionally limit the filenames matching a pattern. Save in your $PATH and make executable, then just use the command above.

Here's the script:

#!/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
查看更多
SAY GOODBYE
7楼-- · 2019-01-07 01:58
cd /path/to/your/folder
sed -i 's/foo/bar/g' *

Occurrences of "foo" will be replaced with "bar".

查看更多
登录 后发表回答