Il n'y a aucun moyen de le faire en utilisant uniquement sed. Vous devrez utiliser au moins l'utilitaire de recherche ensemble :
find . -type f -exec sed -i.bak "s/foo/bar/g" {} \;
Cette commande créera un .bak
fichier pour chaque fichier modifié.
Remarques :
- Le
-i
argument poursed
command est une extension GNU, donc, si vous exécutez cette commande avec lesed
de BSD vous devrez rediriger la sortie vers un nouveau fichier puis le renommer. - Le
find
l'utilitaire n'implémente pas le-exec
argument dans les anciennes boîtes UNIX, vous devrez donc utiliser un| xargs
à la place.
Je préfère utiliser find | xargs cmd
supérieur à find -exec
parce que c'est plus facile à retenir.
Cet exemple remplace globalement "foo" par "bar" dans les fichiers .txt au niveau ou en dessous de votre répertoire actuel :
find . -type f -name "*.txt" -print0 | xargs -0 sed -i "s/foo/bar/g"
Le -print0
et -0
les options peuvent être omises si vos noms de fichiers ne contiennent pas de caractères funky tels que des espaces.
Pour la portabilité, je ne compte pas sur les fonctionnalités de sed spécifiques à Linux ou BSD. Au lieu de cela, j'utilise le overwrite
script du livre de Kernighan et Pike sur l'environnement de programmation Unix.
La commande est alors
find /the/folder -type f -exec overwrite '{}' sed 's/old/new/g' {} ';'
Et le overwrite
script (que j'utilise partout) est
#!/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
L'idée est qu'il écrase un fichier uniquement si une commande réussit. Utile en find
et aussi où vous ne voudriez pas utiliser
sed 's/old/new/g' file > file # THIS CODE DOES NOT WORK
car le shell tronque le fichier avant sed
peut le lire.