Neexistuje způsob, jak to udělat pouze pomocí sed. Budete muset použít alespoň nástroj find společně:
find . -type f -exec sed -i.bak "s/foo/bar/g" {} \;
Tento příkaz vytvoří .bak
soubor pro každý změněný soubor.
Poznámky:
-i
argument prosed
příkaz je rozšíření GNU, takže pokud tento příkaz spouštíte ssed
BSD budete muset přesměrovat výstup do nového souboru a poté jej přejmenovat.find
obslužný program neimplementuje-exec
argument ve starých unixových boxech, takže budete muset použít| xargs
místo toho.
Dávám přednost použití find | xargs cmd
přes find -exec
protože se snáze pamatuje.
Tento příklad globálně nahrazuje „foo“ výrazem „bar“ v souborech .txt ve vašem aktuálním adresáři nebo pod ním:
find . -type f -name "*.txt" -print0 | xargs -0 sed -i "s/foo/bar/g"
-print0
a -0
volby mohou být vynechány, pokud vaše názvy souborů neobsahují funky znaky, jako jsou mezery.
Pokud jde o přenositelnost, nespoléhám na funkce sed, které jsou specifické pro linux nebo BSD. Místo toho používám overwrite
skript z knihy Kernighan a Pike o Unix Programming Environment.
Příkaz je pak
find /the/folder -type f -exec overwrite '{}' sed 's/old/new/g' {} ';'
A overwrite
skript (který všude používám) je
#!/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
Myšlenka je taková, že přepíše soubor pouze v případě, že příkaz uspěje. Užitečné v find
a také tam, kde byste nechtěli použít
sed 's/old/new/g' file > file # THIS CODE DOES NOT WORK
protože shell zkrátí soubor před sed
může si to přečíst.