Ich muss eine Zeichenfolge in vielen Dateien in einem Ordner ersetzen und nur ssh
auf den Server zugreifen. Wie kann ich das machen?
461
cd /path/to/your/folder
sed -i 's/foo/bar/g' *
Vorkommen von "foo" werden durch "bar" ersetzt.
Auf BSD-Systemen wie macOS müssen Sie eine Sicherungserweiterung wie -i '.bak'
"Risikobeschädigung oder Teilinhalt" pro Manpage bereitstellen .
cd /path/to/your/folder
sed -i '.bak' 's/foo/bar/g' *
sed
,-i
erfordert eine Zeichenfolge , nachdem es, die zu den alten Dateinamen angehängt wird. Sosed -i .bak 's/foo/bar/g' *.xx
verschiebt alle.xx
Dateien auf den.xx.bak
Ersatznamen und erzeugt dann die.xx
Dateien mit den foo → bar Substitution.sed -i 's/foo\ with\ spaces/bar/g' *
. Ich nehme an, Sie haben es nach so langer Zeit herausgefunden ... aber auf diese Weise bleibt es für andere, die das gleiche Problem finden.sed -i -e 's/foo/bar/g' $(find /home/user/base/dir)
Ähnlich wie bei Kaspar, jedoch mit dem g-Flag, um alle Vorkommen in einer Zeile zu ersetzen.
Für globale Groß- und Kleinschreibung nicht:
quelle
LC_ALL=C find ./ -type f -exec sed -i '' -e 's/proc.priv/priv/g' {} \;
--include=*.whatever
mit -r.git/
. Stellen Sie sicher, dasscd
Sie auf eine niedrigere Ebene gehen.git status
kehre jetzt zurück :error: bad index file sha1 signature.... fatal: index file corrupt
. Was gibt?Die Antwort von @ kev ist gut, wirkt sich jedoch nur auf Dateien im unmittelbaren Verzeichnis aus. Im folgenden Beispiel wird grep verwendet, um Dateien rekursiv zu finden. Es funktioniert immer für mich.
Befehlsaufschlüsselung
grep -r : --rekursiv , rekursiv alle Dateien unter jedem Verzeichnis lesen.
grep -l : --print-with-Matches , druckt den Namen jeder übereinstimmenden Datei, anstatt übereinstimmende Zeilen zu drucken.
grep -i : --ignore-case .
xargs : transformiere die STDIN in Argumente, folge dieser Antwort .
Der Befehl xargs -i @ ~ enthält @ ~ : einen Platzhalter für das Argument, das an einer bestimmten Position im Befehl ~ verwendet werden soll ~ . Das Zeichen @ ist ein Platzhalter, der durch eine beliebige Zeichenfolge ersetzt werden kann.
sed -i : Bearbeiten Sie vorhandene Dateien ohne Backups.
sed s / regexp / replace / : Ersetzt die Zeichenfolge, die mit regexp übereinstimmt, durch Ersatz .
sed s / regexp / replace / g : global , ersetzen Sie jedes Spiel anstelle nur des ersten Spiels.
quelle
grep --include={*.php,*.html,*.js} -rnl './' -e "old-word" | xargs -i@ sed -i 's/old-word/new-word/g' @
|
, auch warum-i
im Befehl xargs? Ich habe im Handbuch gelesen, dass es veraltet ist und-I
stattdessen verwendet werden sollte. Und wird@
es als Begrenzer für Anfang und Ende des Musters verwendet?grep -rli 'old-word' * | xargs -I@ sed -i '' 's/2.0.0/latest/g' @
rli
) und das@
Zeichen zum BeispielDas hat bei mir funktioniert:
Dies war jedoch nicht der Fall :
sed -i 's/string1/string2/g' *
. Vielleicht sollte "foo" nicht string1 und "bar" nicht string2 sein.quelle
find ./ -type f -exec sed -i '' -e 's/string1/string2/' {} \;
Es gibt einige Standardantworten, die bereits aufgelistet sind. Im Allgemeinen können Sie find verwenden, um die Dateien rekursiv aufzulisten und dann die Vorgänge mit sed oder perl auszuführen .
Für die meisten schnellen Anwendungen ist der Befehl rpl möglicherweise viel einfacher zu merken. Hier ist Ersatz (foo -> bar), rekursiv für alle Dateien:
rpl -R foo bar .
Sie müssen es wahrscheinlich installieren (
apt-get install rpl
oder ähnliches).Für härtere Jobs, die reguläre Ausdrücke und Rückersetzung oder das Umbenennen von Dateien sowie das Suchen und Ersetzen umfassen, ist das allgemeinste und leistungsfähigste Tool, das mir bekannt ist, repren , ein kleines Python-Skript, das ich vor einiger Zeit für einige geschrieben habe dornigere Umbenennungs- und Refactoring-Aufgaben. Die Gründe, die Sie vielleicht bevorzugen, sind:
Um es zu benutzen ,
pip install repren
. Überprüfen Sie die README für Beispiele.quelle
So ersetzen Sie eine Zeichenfolge in mehreren Dateien:
Z.B
Quellblog
quelle
Verwenden Sie den folgenden Befehl, um einen Pfad in Dateien zu ersetzen (Vermeiden von Escapezeichen):
Das @ -Zeichen bedeutet, dass alle Sonderzeichen in einer folgenden Zeichenfolge ignoriert werden sollten.
quelle
Falls Ihre Zeichenfolge einen Schrägstrich (/) enthält, können Sie das Trennzeichen in '+' ändern.
Dieser Befehl würde rekursiv im aktuellen Verzeichnis ausgeführt.
quelle
../domain.com
zudomain.com
Die ersten Zeilenvorkommen von "foo" werden durch "bar" ersetzt. Und Sie können die zweite Zeile verwenden, um zu überprüfen.
quelle
grep -rl 'foo' . | xargs sed -i 's/foo/bar/g'
Wenn Sie eine Liste von Dateien haben, die Sie verwenden können
Wenn Sie alle Dateien haben, können Sie verwenden
Wenn Sie eine Liste von Dateien mit Erweiterung haben, können Sie verwenden
quelle
replace "old_string" "new_string" -- *.txt
replace
Dienstprogramm beziehen. Ohne diese Informationen ist diese Antwort unvollständig."Sie könnten auch find und sed verwenden, aber ich finde, dass diese kleine Perl-Linie gut funktioniert.
"(Auszug aus http://www.liamdelahunty.com/tips/linux_search_and_replace_multiple_files.php )
Meine besten Ergebnisse kommen von der Verwendung von Perl und Grep (um sicherzustellen, dass die Datei den Suchausdruck hat)
quelle
Da Sie nach der Zeichenfolge suchen
search
und diesereplace
durch mehrere Dateien ersetzen möchten , ist dies meine kampferprobte, einzeilige Formel :Schnelle grep Erklärung:
-R
- rekursive Suche-i
- Groß- und Kleinschreibung wird nicht berücksichtigt-I
- Binärdateien überspringen (Sie möchten Text, oder?)-l
- Drucken Sie eine einfache Liste als Ausgabe. Wird für die anderen Befehle benötigtDie grep-Ausgabe wird dann an sed (über xargs) weitergeleitet, das zum tatsächlichen Ersetzen von Text verwendet wird. Das
-i
Flag ändert die Datei direkt. Entfernen Sie es für eine Art "Trockenlauf" -Modus.quelle
Ich habe meine eigene Lösung zusammengestellt, bevor ich diese Frage (und Antworten) gefunden habe. Ich habe nach verschiedenen Kombinationen von "Ersetzen", "Mehrere" und "XML" gesucht, da dies meine Anwendung war, aber diese bestimmte nicht gefunden habe.
Mein Problem: Ich hatte Spring-XML-Dateien mit Daten für Testfälle, die komplexe Objekte enthielten. Ein Refactor für den Java-Quellcode hat viele Klassen geändert und galt nicht für die XML-Datendateien. Um die Testfalldaten zu speichern, musste ich alle Klassennamen in allen XML-Dateien ändern, die auf mehrere Verzeichnisse verteilt waren. Während des Speicherns von Sicherungskopien der ursprünglichen XML-Dateien (obwohl dies kein Muss war, da die Versionskontrolle mich hier speichern würde).
Ich suchte nach einer Kombination von
find
+sed
, weil es in anderen Situationen für mich funktionierte, aber nicht mit mehreren Ersetzungen gleichzeitig.Dann fand ich ask ubuntu response und es half mir beim Aufbau meiner Kommandozeile:
Und es hat perfekt funktioniert (nun, mein Fall hatte sechs verschiedene Ersetzungen). Beachten Sie jedoch, dass alle * .xml-Dateien im aktuellen Verzeichnis berührt werden. Aus diesem Grund und wenn Sie gegenüber einem Versionskontrollsystem rechenschaftspflichtig sind, möchten Sie möglicherweise zuerst filtern und nur an
sed
diejenigen weitergeben, die tatsächlich die gewünschten Zeichenfolgen haben. mögen:quelle
findstr /spin /c:"quéquieresbuscar" *.xml
werden soll : Es wird praktisch sein.quelle
Wirklich lahm, aber ich konnte keinen der sed-Befehle unter OSX zum Laufen bringen, also habe ich stattdessen diese dumme Sache gemacht:
^ - kopiere diese drei Zeilen in meine Zwischenablage (ja, füge die abschließende neue Zeile hinzu), dann:
vi *
und halten Sie Befehl-v gedrückt, bis angezeigt wird, dass keine Dateien mehr vorhanden sind.
Dumm ... hacky ... effektiv ...
quelle
Auf einem MacBook Pro habe ich Folgendes verwendet (inspiriert von https://stackoverflow.com/a/19457213/6169225 ):
quelle
-e
sagt sed nur, dass das nächste Token ein Befehl ist. Verwenden Sie-E
stattdessen für erweiterte reguläre Ausdrücke .Der Stream-Editor ändert mehrere Dateien "inplace", wenn er mit dem
-i
Schalter aufgerufen wird , der eine Sicherungsdatei als Argument verwendet. DamitErsetzt
foo
durchbar
in allen Dateien in diesem Ordner, steigt jedoch nicht in Unterordner ab. Dadurch wird jedoch.bak
für jede Datei in Ihrem Verzeichnis eine neue Datei generiert . Um dies rekursiv für alle Dateien in diesem Verzeichnis und allen seinen Unterverzeichnissen durchzuführen, benötigen Sie einen Helferfind
, um den Verzeichnisbaum zu durchlaufen.find
Ermöglicht Ihnen weitere Einschränkungen hinsichtlich der zu ändernden Dateien, indem Siefind ./ -name '*.php' -or -name '*.html' -print0
ggf. weitere Argumente angeben.Hinweis: GNU
sed
erfordert keine Dateiende undsed -i 's/foo/bar/g' *
funktioniert auch. FreeBSDsed
verlangt eine Erweiterung, lässt aber einen Zwischenraum dazwischen,sed -i .bak s/foo/bar/g *
funktioniert also.quelle
Skript für Multiedit-Befehl
Aus Kaspars Antwort habe ich ein Bash-Skript erstellt, um Befehlszeilenargumente zu akzeptieren und optional die Dateinamen zu begrenzen, die einem Muster entsprechen. Speichern Sie in Ihrem $ PATH und machen Sie es ausführbar. Verwenden Sie dann einfach den obigen Befehl.
Hier ist das Skript:
quelle
Wenn die Datei Backslashes enthält (normalerweise Pfade), können Sie Folgendes versuchen:
Ex:
quelle
Um meinen persönlichen englischen Knoten beizubehalten, habe ich ein Dienstprogramm-Skript geschrieben, mit dessen Hilfe mehrere Paare alter / neuer Zeichenfolgen für alle Dateien in einem Verzeichnis rekursiv ersetzt werden können.
Die mehreren Paare alter / neuer Zeichenfolgen werden in einer Hash-Map verwaltet.
Das Verzeichnis kann über die Befehlszeile oder die Umgebungsvariable festgelegt werden. Die Zuordnung ist im Skript fest codiert. Sie können jedoch den Code ändern, der bei Bedarf aus einer Datei geladen werden soll.
Aufgrund einiger neuer Funktionen ist Bash 4.2 erforderlich.
en_standardize.sh:
quelle
Die Verwendung des Befehls ack wäre viel schneller:
Auch wenn Sie im Suchergebnis einen Leerraum haben. Du musst ihm entkommen.
quelle
Ich gebe ein Beispiel für die Behebung eines häufigen Shebang-Fehlers in Python-Quellen.
Sie können den grep / sed-Ansatz ausprobieren. Hier ist eine, die mit GNU sed funktioniert und kein Git-Repo kaputt macht:
Oder du kannst greptile verwenden :)
Ich habe gerade das erste Skript getestet und das zweite sollte auch funktionieren. Seien Sie vorsichtig mit Escape-Zeichen. Ich denke, es sollte in den meisten Fällen einfacher sein, Greptile zu verwenden. Natürlich können Sie mit sed viele interessante Dinge tun, und dafür ist es möglicherweise vorzuziehen, die Verwendung mit xargs zu beherrschen.
quelle
Ich habe diesen aus einem anderen Beitrag gefunden (kann mich nicht erinnern, welcher) und obwohl er nicht der eleganteste ist, ist er einfach und hat mir als unerfahrener Linux-Benutzer keine Probleme bereitet
Wenn Sie Leerzeichen oder andere Sonderzeichen haben, verwenden Sie ein \
Verwenden Sie für Zeichenfolgen in Unterverzeichnissen **
quelle
Der folgende Befehl kann verwendet werden, um zuerst die Dateien zu durchsuchen und die Dateien zu ersetzen:
Zum Beispiel
quelle
Es gibt einen einfacheren Weg, indem Sie eine einfache Skriptdatei verwenden:
öffne die Datei in gedit oder einem Editor deiner Wahl, ich benutze gedit hier.
Fügen Sie dann im Editor Folgendes in die Datei ein
Speichern Sie die Datei, schließen Sie gedit , Ihr Terminal oder schließen Sie es einfach und starten Sie es, um das neue Skript zu laden, das Sie hinzugefügt haben.
Navigieren Sie zu dem Verzeichnis, in dem Sie mehrere Dateien bearbeiten möchten. Dann renne:
Drücken Sie die Eingabetaste , und dies wird die automatisch ersetzen oldstring und oldstring1 in allen Dateien , die sie mit dem richtigen enthalten newstring und newstring1 sind.
Es werden alle Verzeichnisse und Dateien übersprungen, die nicht die alten Zeichenfolgen enthalten.
Dies kann dazu beitragen, die mühsame Eingabe zu vermeiden, falls Sie mehrere Verzeichnisse mit Dateien haben, die durch Zeichenfolgen ersetzt werden müssen. Sie müssen lediglich zu jedem dieser Verzeichnisse navigieren und dann Folgendes ausführen:
#replace_string_files_present_dir
Alles, was Sie tun müssen, ist sicherzustellen, dass Sie alle Ersatzzeichenfolgen aufgenommen oder hinzugefügt haben, wie ich Ihnen oben gezeigt habe:
replace "oldstring" "newstring" -- *
am Ende der Datei / bin / replace_string_files_present_dir .
Um eine neue Ersetzungszeichenfolge hinzuzufügen, öffnen Sie einfach das von uns erstellte Skript, indem Sie Folgendes in das Terminal eingeben:
sudo gedit /bin/replace_string_files_present_dir
Machen Sie sich keine Sorgen über die Anzahl der hinzugefügten Ersetzungszeichenfolgen. Sie haben keine Auswirkung, wenn die alte Zeichenfolge nicht gefunden wird.
quelle
.gitlab-ci.yml
oder atravis.yml
). Jede Umkehrung, die darin besteht, ein Skript zu schreiben, um es später auszuführen, ist ein Anti-Pattern, da Sie dann die Skript-Erstellung$ replace "From" "To" - `find / path / to / folder -type f`
(replace - ein Dienstprogramm zum Ersetzen von Zeichenfolgen des MySQL-Datenbanksystems)
quelle