Vous pouvez faire quelque chose de grossier avec un petit script Perl qui est chargé d'effectuer des remplacements ligne par ligne ( -l -pe
) en place sur les fichiers passés en arguments ( -i
):
perl -i -l -pe '
if (/from/) { # is the source text present on this line?
printf STDERR ("%s: %s [y/N]? ", $ARGV, $_); # display a prompt
$r=<STDIN>; # read user response
if ($r =~ /^[Yy]/) { # if user entered Y:
s/from/to/g; # replace all occurences on this line
}' /path/to/files
Les améliorations possibles seraient de colorer certaines parties de l'invite et de prendre en charge des éléments tels que «remplacer toutes les occurrences dans le fichier actuel». Demander séparément chaque occurrence sur une ligne serait plus difficile.
Deuxième partie, correspondance des fichiers. s'il n'y a pas trop de fichiers impliqués et que vous exécutez zsh, vous pouvez faire correspondre récursivement tous les fichiers du répertoire actuel et de ses sous-répertoires:
perl -i -l -pe '…' **/*(.)
Si votre shell est bash ≥4, vous pouvez exécuter perl … **/*
, mais cela produira des messages d'erreur parasites car sed tentera (et échouera) de s'exécuter sur les répertoires. Si vous ne souhaitez effectuer le remplacement que dans un ensemble de fichiers tels que les fichiers C, vous pouvez restreindre les correspondances (cela fonctionne en bash ≥4 ou zsh):
perl -i -l -pe '…' **/*.[hc]
Si vous avez besoin d'un contrôle plus fin sur les fichiers que vous remplacez, ou votre shell n'a pas la construction de correspondance de répertoire récursive **
, ou si vous avez trop de fichiers et obtenez une erreur «ligne de commande trop longue», utilisez find
. Par exemple, pour effectuer un remplacement dans tous les fichiers nommés *.h
ou *.c
dans le répertoire en cours et ses sous-répertoires (sur les anciens systèmes, vous devrez peut-être utiliser \;
plutôt +
qu'à la fin de la ligne (le +
formulaire est plus rapide mais n'est pas disponible partout)).
find . -type f -name '*.[hc]' -exec perl -i -l -pe '…' {} +
Cela étant dit, je m'en tiendrai à un éditeur interactif si vous avez besoin d'interaction. Gert a montré un moyen d'y parvenir dans Vim , bien qu'il nécessite d'ouvrir tous les fichiers que vous souhaitez rechercher, ce qui peut être un problème s'il y en a beaucoup.
Dans Emacs, voici comment procéder:
- Rassemblez les noms de fichiers avec
M-x find-name-dired
(spécifiez un répertoire de niveau supérieur) ou M-x find-dired
(spécifiez une find
ligne de commande arbitraire ).
- Dans le tampon dired résultant , appuyez sur
t
pour marquer tous les fichiers, puis sur Q
( dired-do-query-replace-regexp
) pour effectuer un remplacement avec invite sur les fichiers marqués.
s/from/to/g
avec un problème de mise en forme après, plutôts/from/to/gc
qu'avec une emphase sur cellec
que vous avez tenté d'écrire (vous ne pouvez pas le faire avec Markdown, vous pouvez le faire avec<code>
et<strong>
balises HTML).