Rechercher - remplacer avec confirmation
Fred
-
zipe31 Messages postés 38797 Statut Contributeur -
zipe31 Messages postés 38797 Statut Contributeur -
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
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
A voir également:
- Rechercher - remplacer avec confirmation
- Rechercher remplacer word - Guide
- Remplacer disque dur par ssd - Guide
- Rechercher ou entrer l'adresse - Guide
- Confirmation de lecture whatsapp - Guide
- Confirmation de lecture gmail - Guide
3 réponses
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 :
Contenu de chaque fichier :
L'exécution de la ligne de commande avec demande :
Résultat avec remplacement sur fichier 2 et 5 :
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
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 ;((
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
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"
On pourrait aussi bien l'écrire :
Sauf qu'avec ce type de solution, on ne peut pas poser de question à l'utilisateur dans la boucle, ça ne marche pas :
D'où l'idée du
Après, tu as déjà vu un saut de ligne dans un nom de fichier ?
find ./ -type f | while read F; do echo "$F"; done
Sauf qu'avec ce type de solution, on ne peut pas poser de question à l'utilisateur dans la boucle, ça ne marche pas :
find ./ -type f | while read F; do echo "$F"; read -p "Votre réponse : " REPONSE; ... ; done
D'où l'idée du
force qui nécessite la redéfinition de l'IFS.
Après, tu as déjà vu un saut de ligne dans un nom de fichier ?
ben, oui. c'est pourquoi j'alerte.
et c'est pour ça qu'existe cette option (
on peut créer des variables dans un pipe, il faut mettre tout ce qui suit la barre verticale entre accolades :
en shell POSIX :
ou en bash :
en bash, dans un script, on peut conserver le pipe, et y créer des variables réutilisables en dehors, en positionnant l'option lastpipe avec shopt.
et c'est pour ça qu'existe cette option (
-print0), et son pendant dans d'autres programmes (
xargs -0,
sort -z...).
on peut créer des variables dans un pipe, il faut mettre tout ce qui suit la barre verticale entre accolades :
en shell POSIX :
commande | { while... var=blabla; done; echo "$var";}
ou en bash :
while... var="bibi"; done < <(commande)
en bash, dans un script, on peut conserver le pipe, et y créer des variables réutilisables en dehors, en positionnant l'option lastpipe avec shopt.