Es gibt keine Möglichkeit, dies nur mit sed zu tun. Sie müssen mindestens das Find-Dienstprogramm zusammen verwenden:
find . -type f -exec sed -i.bak "s/foo/bar/g" {} \;
Dieser Befehl erstellt einen .bak
Datei für jede geänderte Datei.
Hinweise:
- Die
-i
Argument fürsed
command ist eine GNU-Erweiterung, wenn Sie also diesen Befehl mit demsed
von BSD ausführen Sie müssen die Ausgabe in eine neue Datei umleiten und sie dann umbenennen. - Die
find
Dienstprogramm implementiert nicht den-exec
Argument in alten UNIX-Boxen, also müssen Sie einen| xargs
verwenden stattdessen.
Ich bevorzuge find | xargs cmd
über find -exec
weil es leichter zu merken ist.
Dieses Beispiel ersetzt "foo" global durch "bar" in .txt-Dateien in oder unter Ihrem aktuellen Verzeichnis:
find . -type f -name "*.txt" -print0 | xargs -0 sed -i "s/foo/bar/g"
Die -print0
und -0
Optionen können weggelassen werden, wenn Ihre Dateinamen keine seltsamen Zeichen wie Leerzeichen enthalten.
Für die Portabilität verlasse ich mich nicht auf Funktionen von sed, die spezifisch für Linux oder BSD sind. Stattdessen verwende ich die overwrite
Skript aus dem Buch von Kernighan und Pike über die Unix-Programmierumgebung.
Der Befehl lautet dann
find /the/folder -type f -exec overwrite '{}' sed 's/old/new/g' {} ';'
Und die overwrite
script (das ich überall verwende) ist
#!/bin/sh
# overwrite: copy standard input to output after EOF
# (final version)
# set -x
case $# in
0|1) echo 'Usage: overwrite file cmd [args]' 1>&2; exit 2
esac
file=$1; shift
new=/tmp/$$.new; old=/tmp/$$.old
trap 'rm -f $new; exit 1' 1 2 15 # clean up files
if "[email protected]" >$new # collect input
then
cp $file $old # save original file
trap 'trap "" 1 2 15; cp $old $file # ignore signals
rm -f $new $old; exit 1' 1 2 15 # during restore
cp $new $file
else
echo "overwrite: $1 failed, $file unchanged" 1>&2
exit 1
fi
rm -f $new $old
Die Idee ist, dass eine Datei nur dann überschrieben wird, wenn ein Befehl erfolgreich ist. Nützlich in find
und auch dort, wo Sie es nicht verwenden möchten
sed 's/old/new/g' file > file # THIS CODE DOES NOT WORK
da die Shell die Datei vor sed
abschneidet kann es lesen.