Antworten:
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. So sed -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.
find ./ -type f -exec sed -i 's/string1/string2/g' {} \;
Für globale Groß- und Kleinschreibung nicht:
find ./ -type f -exec sed -i 's/string1/string2/gI' {} \;
LC_ALL=C find ./ -type f -exec sed -i '' -e 's/proc.priv/priv/g' {} \;
--include=*.whatever
mit -r
.git/
. Stellen Sie sicher, dass cd
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.
grep -rli 'old-word' * | xargs -i@ sed -i 's/old-word/new-word/g' @
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.
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 Beispiel
Das hat bei mir funktioniert:
find ./ -type f -exec sed -i 's/string1/string2/' {} \;
Dies war jedoch nicht der Fall : sed -i 's/string1/string2/g' *
. Vielleicht sollte "foo" nicht string1 und "bar" nicht string2 sein.
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.
Verwenden Sie den folgenden Befehl, um einen Pfad in Dateien zu ersetzen (Vermeiden von Escapezeichen):
sed -i 's@old_path@new_path@g'
Das @ -Zeichen bedeutet, dass alle Sonderzeichen in einer folgenden Zeichenfolge ignoriert werden sollten.
Falls Ihre Zeichenfolge einen Schrägstrich (/) enthält, können Sie das Trennzeichen in '+' ändern.
find . -type f -exec sed -i 's+http://example.com+https://example.com+g' {} +
Dieser Befehl würde rekursiv im aktuellen Verzeichnis ausgeführt.
../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.
grep -rl 'foo' . | xargs sed -i 's/foo/bar/g'
grep 'foo' -r * | awk -F: {'print $1'} | sort -n | uniq -c
grep -rl 'foo' . | xargs sed -i 's/foo/bar/g'
Wenn Sie eine Liste von Dateien haben, die Sie verwenden können
replace "old_string" "new_string" -- file_name1 file_name2 file_name3
Wenn Sie alle Dateien haben, können Sie verwenden
replace "old_string" "new_string" -- *
Wenn Sie eine Liste von Dateien mit Erweiterung haben, können Sie verwenden
replace "old_string" "new_string" -- *.extension
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.
perl -pi -w -e 's/search/replace/g;' *.php
"(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)
perl -pi -w -e 's/search/replace/g;' $( grep -rl 'search' )
Da Sie nach der Zeichenfolge suchen search
und diese replace
durch mehrere Dateien ersetzen möchten , ist dies meine kampferprobte, einzeilige Formel :
grep -RiIl 'search' | xargs sed -i 's/search/replace/g'
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.
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:
find -name "*.xml" -exec sed -s --in-place=.bak -e 's/firstWord/newFirstWord/g;s/secondWord/newSecondWord/g;s/thirdWord/newThirdWord/g' {} \;
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:
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' {} \;
findstr /spin /c:"quéquieresbuscar" *.xml
werden soll : Es wird praktisch sein.
Wirklich lahm, aber ich konnte keinen der sed-Befehle unter OSX zum Laufen bringen, also habe ich stattdessen diese dumme Sache gemacht:
:%s/foo/bar/g
:wn
^ - 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 ...
Auf einem MacBook Pro habe ich Folgendes verwendet (inspiriert von https://stackoverflow.com/a/19457213/6169225 ):
sed -i '' -e 's/<STR_TO_REPLACE>/<REPLACEMENT_STR>/g' *
-i ''
stellt sicher, dass Sie keine Backups erstellen.
-e
für moderne Regex.
-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. Damit
sed -i.bak 's/foo/bar/g' *
Ersetzt foo
durch bar
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 Helfer find
, um den Verzeichnisbaum zu durchlaufen.
find ./ -print0 | xargs -0 sed -i.bak 's/foo/bar/g' *
find
Ermöglicht Ihnen weitere Einschränkungen hinsichtlich der zu ändernden Dateien, indem Sie find ./ -name '*.php' -or -name '*.html' -print0
ggf. weitere Argumente angeben.
Hinweis: GNU sed
erfordert keine Dateiende und sed -i 's/foo/bar/g' *
funktioniert auch. FreeBSD sed
verlangt eine Erweiterung, lässt aber einen Zwischenraum dazwischen, sed -i .bak s/foo/bar/g *
funktioniert also.
Skript für Multiedit-Befehl
multiedit [-n PATTERN] OLDSTRING NEWSTRING
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:
#!/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
Wenn die Datei Backslashes enthält (normalerweise Pfade), können Sie Folgendes versuchen:
sed -i -- 's,<path1>,<path2>,g' *
Ex:
sed -i -- 's,/foo/bar,/new/foo/bar,g' *.sh (in all shell scripts available)
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:
#! /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
Die Verwendung des Befehls ack wäre viel schneller:
ack '25 Essex' -l | xargs sed -i 's/The\ fox \jump/abc 321/g'
Auch wenn Sie im Suchergebnis einen Leerraum haben. Du musst ihm entkommen.
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:
$ grep -rli --exclude '*.git*' '#!/usr/bin/python' . | xargs -I {} \
gsed -i '' -e 's/#!\/usr\/bin\/python/#!\/usr\/bin\/env python/' {}
Oder du kannst greptile verwenden :)
$ greptile -x .py -l -i -g '#!/usr/bin/env python' -r '#!/usr/bin/python' .
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.
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
for i in *old_str* ; do mv -v "$i" "${i/\old_str/new_str}" ; done
Wenn Sie Leerzeichen oder andere Sonderzeichen haben, verwenden Sie ein \
for i in *old_str\ * ; do mv -v "$i" "${i/\old_str\ /new_str}" ; done
Verwenden Sie für Zeichenfolgen in Unterverzeichnissen **
for i in *\*old_str\ * ; do mv -v "$i" "${i/\old_str\ /new_str}" ; done
Es gibt einen einfacheren Weg, indem Sie eine einfache Skriptdatei verwenden:
# sudo chmod +x /bin/replace_string_files_present_dir
öffne die Datei in gedit oder einem Editor deiner Wahl, ich benutze gedit hier.
# sudo gedit /bin/replace_string_files_present_dir
Fügen Sie dann im Editor Folgendes in die Datei ein
#!/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.
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:
#replace_string_files_present_dir
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.
.gitlab-ci.yml
oder a travis.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)