J'ai exécuté ce qui suit pour remplacer un terme utilisé dans tous les fichiers du répertoire de travail actuel:
$ find . -type f -print0 | xargs -0 sed -i'.bup' -e's/Ms. Johnson/Mrs. Melbin/g'
Cela a effectué la substitution de mots mais a également créé des .bup
fichiers de fichiers qui n'ont jamais eu la Ms. Johnson
chaîne.
Comment effectuer la substitution sans créer toutes ces sauvegardes inutiles?
linux
shell-script
scripting
sed
Belmin Fernandez
la source
la source
ex
et conditionnellement (uniquement si le fichier est modifié) en cours d'exécution:!cp '%' '%.bup'
avant l'enregistrement et la fermeture. Il serait peut-être intéressant d'y regarder de plus près.vi
échange de pile.Réponses:
Vous pouvez vérifier le contenu des fichiers pour vous assurer qu'une substitution aura lieu lors
sed
de leur fonctionnement:Si vous voulez vraiment être intelligent, vous pouvez renoncer à utiliser
find
du tout:la source
'{}'
juste avant\;
dans ce-exec
.Find possède un
-exec
opérateur qui exécute une commande arbitraire. Encore mieux,-exec
est un test , donc vous pouvez enchaîner plusieurs-exec
s ensemble, et si les commandes précédentes échouent, les dernières ne seront pas exécutées. La chaîne{}
est remplacée par le nom de fichier actuel et;
marque la fin de la commande. Vous devez citer les deux pour éviter que le shell interfère.Donc:
la source
{}
dans la chaîne nulle lors de l'expansion de l'accolade.J'ai regardé la page de manuel et je n'ai vu aucun moyen de le faire directement
sed
, comme je suis sûr que vous l'avez fait avant de le demander. Je vois plusieurs façons de contourner cela en utilisant grep, mais je pense que le plus simple est le suivant:-r
recurse-l
print nom de fichier uniquement les-Z
noms de fin avec nullla source
Il semble que vous devez d'abord créer une liste de fichiers qui correspondent à vos termes de recherche.
la source
.
comme premier argumentfind
. De plus, comme j'ai été informé moi-même il n'y a pas si longtemps, vous n'avez pas vraiment besoin de citer ou d'échapper à{}
find
Génère d' abord une liste de fichiers séparés par des sauts de ligne, puis le shell décompose cette liste dans n'importe quel espace (pas seulement les retours à la ligne), puis le shell traite chaque mot comme un modèle global. Cela ne fonctionne que si vos noms de fichiers ne contiennent pas d'espaces ou\[?*
. D'autres réponses sur cette page montrent comment procéder correctement..
n'est pas nécessaire avec find (au moins find trouvé sur linux) car il est supposé qu'aucun argument ne passe par aucun chemin.