Menu

Rechercher - remplacer avec confirmation

- - Dernière réponse : zipe31
Messages postés
36510
Date d'inscription
dimanche 7 novembre 2010
Statut
Contributeur
Dernière intervention
17 mai 2019
- 14 mai 2019 à 21:17
Bonjour,

Je cherche à faire des "rechercher remplacer "récursivement dans des fichiers en affichant les fichiers modifiés ou en demandant confirmation avant remplacement pour éviter toute boulette...

Voici ce que j'ai trouvé :
- Afficher le motif à remplacer dans une recherche récursive
find -type f | xargs grep -l "motif_a_remplacer" -> mais j'ai des erreurs avec certains fichiers : "Aucun fichier ou dossier de ce type"

- Remplacer le motif
find -type f -exec sed -i 's/motif_a_remplacer/motif_de_remplacement/g' {} \;
A priori ça marche mais j'aimerais avant de faire le remplacement : soit en demander confirmation (Oui/non) soit en affichant juste la liste des fichiers qui seraient modifiés.


Une idée ?
Merci
Fred


Configuration: Windows / Firefox 66.0
Afficher la suite 

Votre réponse

3 réponses

Messages postés
1189
Date d'inscription
lundi 2 mai 2016
Statut
Membre
Dernière intervention
17 mai 2019
164
0
Merci
Salut,

Je n'ai pas testé en récursif, ni avec plusieurs remplacements dans le même fichier, mais l'idée est là, à toi d'adapter à ton cas :

Liste des fichiers :
$ tree
.
├── fich1
├── fich2
├── fich3
├── fich4
└── fich5

0 directories, 5 files


Contenu de chaque fichier :
$ more f*
::::::::::::::
fich1
::::::::::::::
motif
::::::::::::::
fich2
::::::::::::::
motif
::::::::::::::
fich3
::::::::::::::
motif
::::::::::::::
fich4
::::::::::::::
motif
::::::::::::::
fich5
::::::::::::::
motif


L'exécution de la ligne de commande avec demande :
$ find . -type f -exec bash -c 'grep -Hn "m" ${1};read -p "Remplacer ?" rep;if [ "${rep}" == o ];then sed -i "s/motif/AAA/" ${1};fi' _ {} \;
./fich5:1:motif
Remplacer ?o
./fich4:1:motif
Remplacer ?n
./fich3:1:motif
Remplacer ?n
./fich2:1:motif
Remplacer ?o
./fich1:1:motif
Remplacer ?n


Résultat avec remplacement sur fichier 2 et 5 :
$ more f*
::::::::::::::
fich1
::::::::::::::
motif
::::::::::::::
fich2
::::::::::::::
AAA
::::::::::::::
fich3
::::::::::::::
motif
::::::::::::::
fich4
::::::::::::::
motif
::::::::::::::
fich5
::::::::::::::
AAA

Commenter la réponse de UnGnU
0
Merci
Merci de ton aide !
Bon après c'est un peu du chinois la syntaxe pour moi...
Quand il ne trouve pas le contenu "motif" dans le fichier, il pose tout de même la question ;((
Remplacer ?n
Remplacer ?n
Remplacer ?n
Remplacer ?n
Remplacer ?n
Commenter la réponse de Fred
0
Merci
Voici ce que je vais finalement utiliser (merci Bruno !)

# sauvegarder la valeur du séparateur (pour la boucle for), en principe c'est un espace
IFS_BAK="$IFS"

# définir une autre valeur de séparateur : le retour à la ligne
IFS=$( echo -e "\n" )

# boucle sur tous les fichiers trouvés récursivement à partir du répertoire courant
for F in $( find ./ -type f )
do
# faire un test pour savoir si le fichier contient la chaine recherchée
TEST=$( grep 'monancienneadresse\.gmail' "$F" )

# si le test est positif
if [ "$TEST" != "" ]
then
# question
read -p "Remplacer dans $F ?" REPONSE
# si la réponse est o, faire le remplacement sur le fichier (attention, avec -i ça le fait!!!)
[ "$REPONSE" == "o" ] && sed -i 's/monancienneadresse\.gmail/manouvelle\.fr/g' "$F"
fi
done

# rétablir le séparateur par défaut
FS="$IFS_BAK"
boxR
Messages postés
4
Date d'inscription
mardi 14 mai 2019
Statut
Membre
Dernière intervention
14 mai 2019
-
Fred, ça donnerai par exemple :
find ./ -type f -print0 | while read -d '' F ; do TEST=$( grep 'monancienneadresse\.gmail' "$F" ); if [ "$TEST" != "" ]; then read -p "Remplacer dans $F ? " REPONSE < /dev/tty; [ "$REPONSE" == "o" ] && sed -i 's/monancienneadresse\.gmail/manouvelle\.fr/g' "$F"; fi; done
À tester bien sûr...
lEprofSonDkon
Messages postés
162
Date d'inscription
jeudi 13 décembre 2018
Statut
Membre
Dernière intervention
17 mai 2019
6 > boxR
Messages postés
4
Date d'inscription
mardi 14 mai 2019
Statut
Membre
Dernière intervention
14 mai 2019
-
à noter que, par convention, les noms de variables tout en majuscules sont réservés aux variables d'environnement (HOME, PATH...).
zipe31
Messages postés
36510
Date d'inscription
dimanche 7 novembre 2010
Statut
Contributeur
Dernière intervention
17 mai 2019
5785 > boxR
Messages postés
4
Date d'inscription
mardi 14 mai 2019
Statut
Membre
Dernière intervention
14 mai 2019
-
Salut vous trois,

Perso hier j'avais testé avec ça :

find . -type f -exec bash -c 'grep -Hn "to" ${1} && (read -p "Remplacer ? " rep;if [ "${rep}" == o ];then sed "s/toto/AAA/" ${1};fi;) || >/dev/null' _ {} \;


Pour faire plaisir à "lEprofSonDkon", on peut rajouter
-print0
à find et
-z
à grep, et tout le monde il sera content ;-))
lEprofSonDkon
Messages postés
162
Date d'inscription
jeudi 13 décembre 2018
Statut
Membre
Dernière intervention
17 mai 2019
6 > zipe31
Messages postés
36510
Date d'inscription
dimanche 7 novembre 2010
Statut
Contributeur
Dernière intervention
17 mai 2019
-
fais-moi plaisir, encore, et mets donc des guillemets autour des
$1
(les accolades sont inutiles, et elles perturbent la lecture : elles pourraient être assimilées au
{}
de find).

mais pourquoi
|| >/dev/null
?
zipe31
Messages postés
36510
Date d'inscription
dimanche 7 novembre 2010
Statut
Contributeur
Dernière intervention
17 mai 2019
5785 > lEprofSonDkon
Messages postés
162
Date d'inscription
jeudi 13 décembre 2018
Statut
Membre
Dernière intervention
17 mai 2019
-
mais pourquoi
|| >/dev/null
?
À cause de ça ;-\

J'ai mis ça, mais un
echo "Rien à faire"
l'eut fait aussi ;-)
Commenter la réponse de Fred