2009-02-09 4 views
33

Was ist der beste Weg, dies zu tun? Ich bin kein Command Line Warrior, aber ich dachte, dass es vielleicht einen Weg gibt, Grep und Cat zu benutzen.Die beste Möglichkeit, in mehreren Dateien zu suchen/zu ersetzen?

Ich möchte nur eine Zeichenfolge ersetzen, die in einem Ordner und Unterordnern auftritt. Was ist der beste Weg, dies zu tun? Ich führe ubuntu, wenn das wichtig ist.

-d

+0

Nur um diesen Link hier zu verlassen: http://StackOverflow.com/Questions/102083/whats-the-best-tool-find-and-replace-regular-expressions-over-multiple-files –

Antwort

36
find . -type f -print0 | xargs -0 -n 1 sed -i -e 's/from/to/g' 

Der erste Teil davon ist ein Befehl find die Dateien, die Sie ändern möchten, zu finden. Möglicherweise müssen Sie das entsprechend ändern. Der "xargs" -Befehl nimmt jede gefundene Datei und wendet den Befehl "sed" darauf an. Der Befehl "sed" übernimmt jede Instanz von "from" und ersetzt sie durch "to". Dies ist ein standardmäßiger regulärer Ausdruck, also ändern Sie ihn nach Bedarf.

Wenn Sie Svn verwenden, Vorsicht. Ihre .svn-Verzeichnisse werden ebenfalls gesucht und ersetzt. Sie müssen diejenigen, beispielsweise wie folgt auszuschließen:

find . ! -regex ".*[/]\.svn[/]?.*" -type f -print0 | xargs -0 -n 1 sed -i -e 's/from/to/g'

oder

find . -name .svn -prune -o -type f -print0 | xargs -0 -n 1 sed -i -e 's/from/to/g'

+0

es scheint nicht wie dieser Befehl in Unterverzeichnisse rekursiv. Ist da etwas, was ich falsch mache? – blackrobot

+0

Was lässt Sie glauben, dass es nicht in Verzeichnissen rekursiv ist? –

+0

Die Textdateien in den Unterverzeichnissen nehmen die Änderungen nicht vor. was ich will, ist dies: Ändern Sie Vorkommen von some.ip.address auf einigewebsite.com in allen Unterverzeichnissen. – blackrobot

37

Wie Paulus sagte, Sie wollen zuerst die Dateien, die Sie bearbeiten möchten, finden und dann bearbeiten. Eine Alternative Fund zu verwenden ist GNU grep zu verwenden (die Standardeinstellung auf Ubuntu), zB:

grep -r -l from . | xargs -0 -n 1 sed -i -e 's/from/to/g' 

Sie können auch ack-grep verwenden (sudo apt-get ack-grep installieren oder http://petdance.com/ack/ besuchen), als auch, wenn Sie wissen, dass Sie nur einen bestimmten Dateityp wünschen und Dinge in Versionskontrollverzeichnissen ignorieren möchten. zB wenn Sie Textdateien wollen,

ack -l --print0 --text from | xargs -0 -n 1 sed -i -e 's/from/to/g' 
# `from` here is an arbitrary commonly occurring keyword 

Eine Alternative zu sed verwendet, ist Perl zu verwenden, die mehrere Dateien pro Befehl verarbeiten kann, zB

grep -r -l from . | xargs perl -pi.bak -e 's/from/to/g' 

Hier Perl erzählt bearbeiten in platzieren Sie eine .bak-Datei zuerst.

Sie können beliebige der linken Seiten des Rohrs mit den rechten Seiten kombinieren, je nach Vorliebe.

+0

Sie können Versionskontrollverzeichnisse in "find" mit dem Befehl "-prune" vermeiden. Zum Beispiel "find. -name RCS -prune -o -type f -print0" –

+0

Richtig, obwohl es weniger Intelligenz benötigt, um ein Tool wie ack für Sie zu haben. –

+0

ack akzeptiert auch eine '--print0' Option, um null als Trennzeichen zwischen Dateinamen zu verwenden, also würde Ihr ack Befehl wie folgt aussehen:' ack -l --print0 --text from | xargs -0 -n 1 sed -i -e's/from/to/g'' –

3

Eine Alternative zu sed verwendet rpl (zB erhältlich von http://rpl.sourceforge.net/ oder Ihrem GNU/Linux-Distribution), wie rpl --recursive --verbose --whole-words 'F' 'A' grades/

14

ich in einem anderen Beispiel für Leute werfen würde Ag, The Silver Searcher Suchen/Ersetzen Operationen auf mehreren Dateien zu tun mit .

Komplettes Beispiel:

ag -l "search string" | xargs sed -i '' -e 's/from/to/g' 

Wenn wir diese brechen, was wir bekommen, ist:

# returns a list of files containing matching string 
ag -l "search string" 

Als nächstes haben wir:

# consume the list of piped files and prepare to run foregoing command 
# for each file delimited by newline 
xargs 

Schließlich wird der String Ersatz Befehl :

# -i '' means edit files in place and the '' means do not create a backup 
# -e 's/from/to/g' specifies the command to run, in this case, 
# global, search and replace 

sed -i '' -e 's/from/to/g'