Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#176 Le 07/04/2020, à 13:36

ar barzh paour

Re : [Projet terminé] correction anomalie de grub

je voulais mettre une version plus à jour ici mais je n'arrive plus à relire les post 172 et 173 avec Firefox (j'ai déjà signalé cette anomalie mais non corrigée à ce jour)
modif_grub_v46_bis et recup_fstab_V8
corrige une anomalie concernant le label de la partition EFI (sans conséquence)
dans ces fichiers remplacer

if grep "LABEL"     <<< $ligne par      if grep " LABEL" <<< $ligne
if grep UUID         <<< $ligne par      if grep " UUID" <<< $ligne
if grepTYPE          <<< $ligne par      if grep " TYPE" <<< $ligne
if grep PARTUUID     <<< $ligne par      if grep " PARTUUID" <<< $ligne

PC          : B760M DS3H DDR4,  12th Gen Intel(R) Core(TM) i3-12100, RAM DDR4 8GiB -2400 Ubuntu 20.04, 22.04, 24.04 (en test )
Portable1 : ThinkPad P50 I7-6820HQ, 16G0 Ram Ubuntu 22.04 Ubuntu 24.04 , W10-PRO( en voyage )
Portable2 : T5750  @ 2.00GHz RAM 1GiB DDR2 667 Mhz Ubuntu 20.04 ( batterie HS )
stourm a ran war bep tachenn (Angela Duval) ( Je combats sur tous les fronts )

Hors ligne

#177 Le 16/04/2020, à 16:27

ar barzh paour

Re : [Projet terminé] correction anomalie de grub

avec Violent Monkey j'arrive maintenant à relire les post
donc pour ceux que ça intéresse ( je pense qu'il n'y a pas beaucoup de monde) voici la dernière version
/media/SH/grub/V46/modif_grub_V46_bis qui va de paire avec recup_fstab_v8
pour rappel modif_grub lance recup_fstab
que je poste dans les deux post suivants


PC          : B760M DS3H DDR4,  12th Gen Intel(R) Core(TM) i3-12100, RAM DDR4 8GiB -2400 Ubuntu 20.04, 22.04, 24.04 (en test )
Portable1 : ThinkPad P50 I7-6820HQ, 16G0 Ram Ubuntu 22.04 Ubuntu 24.04 , W10-PRO( en voyage )
Portable2 : T5750  @ 2.00GHz RAM 1GiB DDR2 667 Mhz Ubuntu 20.04 ( batterie HS )
stourm a ran war bep tachenn (Angela Duval) ( Je combats sur tous les fronts )

Hors ligne

#178 Le 16/04/2020, à 16:29

ar barzh paour

Re : [Projet terminé] correction anomalie de grub

pour rappel : il faut copier ce fichier ET le fichier (recup_fstab) du post suivant dans unrépertoire et lancer modif_grub
et il y aura création d'un fichier grub que l'on pourra analyser avant de remplacer l'original ! (au choix)


le fichier modif_grub_V46_bis

#!/bin/bash
nom_base=`echo $(basename $0)`
nom_dir=`echo $(dirname $0)`
echo "$nom_base"
echo "$nom_dir"

#########################################################################################
# résumé des actions effectuées
# modif_grub permet
#  - de raccourcir la longueur d'un fichier au format grub 
#       en y supprimant des menus inutiles (menu contenant /dev /dev , uuid différents)
#    le fichier à traiter doit contenir
#                pemière ligne  : un commentaire commençant par #
#                la ligne       : ### BEGIN /etc/grub.d/10_linux ###
#
#                si la ligne    : ### BEGIN /etc/grub.d/40_custom ### apparait
#                seules les lignes entre 10_linux et 40_custom seront traitées
#                si cette ligne n'apparait pas
#                ce sont les lignes de 10_linux à la fin qui seront traitées           
#
#    un menu doit être de la forme 
#          menuentry ' ............ {  ou   menuentry " ..........{
#          des lignes intermédiaires à priori quelconques
#          la ligne terminant le menu ........ }
#
#    aucun caractère [hors blancs] ne doit apparaître après un { ou un }
#
#    un submenu doit être de la forme
#          submenu '................{ ou submenu "................{
#          des lignes quelconques ?
#          de menus au format ci-dessus
#          une ligne de fermeture    ......}    aucun caractères [hors blancs] après }
#          si cette ligne fait partie d'un menu elle sera alors de la forme
#               .........}    }
#       
#  - d'ajouter un label à un menu de grub pour avoir une présentation plus claire
#         pour cela deux solutions : 
#                        - utilisation du label de la partition
#                        - utilisation d'un fichier personnel au format blkid
#                          chaque ligne devra commencée par /dev/xxx:
#                          chaque ligne devra contenir UUID=
#                          un caractère espace est nécessaire devant les champs utilisés
#                            ( LABEL UUID TYPE  !!! ) 
#         lorsqu'un label est modifié et que l'on retraite le fichier , ce label sera 
# - l'action de remplacement d'un grub réel demande à l'utilisateur des précautions d'usage
#            être capable de revenir en arrière si problème !
#            c'est à dire être capable de remettre le grub d'origine
#########################################################################################

#########################################################################################
# les fichiers créés
#     les fichiers créés par recup_fstab
#         le fichier blkid-res.txt      ( correspondance dev-uuid-label)
#         le fichiers UBoot-UPart.txt   ( cas des OS avec boot séparé)
#         ce fichier est nécessaire (même vide) s'il est absent , le programme s'arêtera
#     ZZZnum est un répertoire créée dans le répertoire courant
#     les fichiers créés par recup_fstab dans ZZZnum
#         le fichier DevSd-UBoot-UPart-<date> : contient les fichiers de /etc/fstab
#         le fichier UBoot-UPart-<date>.txt   : copie de  UBoot-UPart.txt
#
#     les autres fichiers qui sont créés dans ZZZnum par modif_grub
#         le fichier grub-OK-<date>-<....>.txt destiné à remplacer le fichier traité
#            ce fichier n'apparait plus si on a demandé le remplacement du fichier traité
#                 mais dans ce cas le fichier traité est sauvegardé (dans son nom-<date>)
#         les fichiers suivants sont plus ou moins intéressant à analyser
#             fichier grub-sup : contient les menus qui ont été supprimés
#             fichier stat-<date> : contient nombre de menus/lignes conservés/supprimés 
#             fichier grub-mod : contient la 1ére ligne d'un menu qui a été modifié
#                                           ou qui a été conservé pour une raison X
#             les fichiers tmp[012]-<date> (coupures du fichier traité) 
#########################################################################################

# quelques points d'historique
# V46++2020-04-11 ajout stat nb_lignes mod
#                 # remplacement [espacetab] par [[:blank:]] lignes 710-713-1409-1412-1424-1425
#                 # ok
#      2020-04-13 dans critere de suppression_2 ajout de la recherche de l'UUID par le /dev dans linux       
# V46+ 2020-04-07 " LABEL" au lieu de "LABEL" dans grep et  " TYPE" " UUID" " PARTUUID"
# V46 2018-11-23 utilisation de sed -r 's/.*\bLABEL="([^"]+)".*/\1/' 
#      au lieu de  LABEL=${ligne#*LABEL=?} et LABEL=${LABEL%%\"*} #"
#       fonctionne avec recup_fstab_V8 (idem ci-dessus)
# V44 2018-04-07 correction anomalie labels tronqués s'ils comportent des espaces
#     concerne le $ récupération dev label uuid btype dans le fichier choisi vers ligne 1240
#     fonctionne avec recup_fstab_V7 ( idem modification pour les labels tronqués )
# V43 2018-02-13 fonctionne avec V6
# V41 2017-03-23
#     prend en compte le changement de label par un autre label
#     ne fonctionnera que
#     si on traite un grub modifié par modif_grub à partir de V7 
#     remarque on peut aussi repartir d'un grub tout neuf par update-grub
#     les grub de tous les OS doivent être dans cet état
#     on peut le voir si la ligne du menu entry comporte  : après le label
#     exemple     	menuentry 'U16.04-P10-64b : Ubuntu, avec Linux .......  
#     par contre la ligne suivante avec un nouveau label NOUVEAU
#     	menuentry 'M16.04-P12-64b,Ubuntu  (sur /dev/sda12)' 
#     deviendrait
#     	menuentry 'NOUVEAU : M16.04-P12-64b,Ubuntu  (sur /dev/sda12)'

# V40 qui fonctionne avec recup_fstab_V5
#     les fichiers créés prennent un nom plus long (répertoire complet)
#     les statistiques sont conservées dans ZZZnum/stat-<date>
#     pour des raisons d'affichage , les _ des noms de fichiers créés sont remplacés par des -

# V39 répertoire des fichiers temporaires ZZZnum
#    demande de suppression fichers

# V38 avec recup_fstab_V4
#       ajout de l'option --sansfstab (permet de na pa lancer recup_fstab)
#  ===> la création du fichier de concordance UUID-Part-UUIDBoot ne sera pas faite
#       (hors ce fichier est nécessaire à modif_grub )
#       et le fichier blkid ne sera pas mis à jour automatiquement

# V35 le programme ne traite plus que les lignes comprises entre 
#     ### BEGIN /etc/grub.d/10_linux ###
# et
#     ### BEGIN /etc/grub.d/40_custom ###
#    le fichier à traiter doit commencer par un #
#    la ligne ### BEGIN /etc/grub.d/10_linux ### est obligatoire
#    mais ne doit pas commencer le fichier
#    si la ligne ### BEGIN /etc/grub.d/40_custom ### est absente
#    le programme traitera le fichier de 10_linux jusqu'à la fin

# V34 suppression de certaines fonctions devenue inutiles
#     réorganisation de certaines fonctions

# V33 ajout du sous programme recup_fstab_V2 ( étude système à boot séparé)

# V30 idem V29 sans les commentaires superflus
# si boot séparé on sort !!!!

# V29 2017-03-09
# correction due à l'utilisation de ${#uuid[*]} dans la construction concordance label-uuid
# remplacement de tous les while ${#menu[*]} par for ${!menu[@]}

# V28 2017-03-08
# présentation de concordances UUID-LABEL
# un ligne menuentry et submenu peut comporter des blank après   } 
# une ligne peut se terminer par }  }

#V26 function sort_info_transforme donne des traces

# V25 
# chaine_linux="linux.*\/vmlinu" pour prise en compte de "linux	/@/boot/vmlinuz"

# V8 2017-02-14
# adjonction critere_suppression_2
# suppression des menus qui ont des UUID différents dans search --no-floppy et dans linux /boot/
# conservation des menus qui n'ont pas de lignes search --no-floppy
# conservation des menus qui n'ont pas de lignes linux /boot/vmlinu
# anomalie redoublement label , non modification de la ligne submenu

# V7 2017-02-13
# la ligne de submenu est recherché par submenu ' ou par submenu " au lieu de submenu 'Options ..... 
# l' UUID (et donc le label) est récupéré dans le bloc suivant de menuentry


# V6 2017-02-13
# on récupère l'UUID dans la ligne search --no-floppy --fs-uuid --set=root du bloc

# V5 2017-02-12
# seules les lignes commençant par menuentry et finisant par { seront traitées comme menuentry
#       (le test se fait par ^[tab ]*menuentry.*{$)

# V4 2017-02-10
# il y aura suppression du menu si on trouve  ....../dev/sd...../dev/sd...... AVANT la chaine --class  ,
########################################################################################    




function confirmation_sortie {
	declare titre="Sortie de $0"                                # variables locales
	declare ok="Confirmer la sortie"
	declare texte="Pour Validez la sortie cliquer sur \"$ok\""
	declare cancel="Abandonner la sortie"

	if zenity --question --title "$titre" --text "$texte" \
              --no-wrap --ok-label "$ok" --cancel-label "$cancel"
		then
			exit 63
		fi
}

function suppression_fichiers_temporaires {
    repertoire_a_vider="./$ZZZnum"
    fich="/tmp/liste_fichier.txt" # contient la liste des fich. du rép. à supprimer
    oklabel="Sortir si EXIT coché  / Supprimer fichiers cochés sinon"
    cancellabel="Re-cocher toutes les cases (sauf grub-OK)"
    texte="
        Des fichiers ont été créés lors de l'exécution du programme
            $0
        ci dessous ces fichiers encore existants dans le répertoire
        $repertoire_a_vider

        Pour supprimer un/des fichiers 
            1- Décochez la case EXIT 
            2- Cochez   la case du/des fichier(s) que vous voulez supprimer
            3- Cliquer sur $oklabel
               ==> ce menu se relancera en indiquant
                   les fichiers encore existants dans le répertoire $repertoire_a_vider

        Pour SORTIR de ce menu une seule solution
               Cochez la case EXIT puis cliquez sur \"$oklabel\"

         pour Recocher la case de tous les fichiers (sauf grub-OK) cliquer sur la case
             $cancellabel
            "
while :
    do
        # listage des fichiers du répertoire
        ls "$repertoire_a_vider" > "$fich" # ligne à supprimer en réel
        liste_fichier="TRUE EXIT_(Sortir_du_menu)"
        while read ligne
            do                                    # problème zenity ?
                ligne=$(sed "s/ /*/g" <<< $ligne) # remplacer les espaces par *
                case $ligne in
                
                    tmp[012][-_]20*         |     \
                    tmp[-_]u[-_]l*          |     \
                    tmp.txt                 |     \
                    fich[-_]transforme-*    |     \
                    grub-mod*               |     \
                    stat-20*                |     \
                    DevSd[-_]UBoot*         |     \
                    grub-sup-20*            |     \
                    UBoot-UPart*            )
                    liste_fichier="$liste_fichier TRUE $ligne"    ;;
                    
                    blkid-res.txt           |     \
                    grub-OK*                )
                    liste_fichier="$liste_fichier FALSE $ligne"   ;;
                    
                    esac
            done < "$fich"

    #sélection des fichiers à supprimer

    choix=`zenity --list                    \
      --title="XXXXXXXXXXXXXXXXXXX : $0"    \
      --text="$texte"                       \
      --checklist                           \
      --cancel-label "$cancellabel"         \
      --ok-label "$oklabel"                 \
      --height "750"                        \
      --width "800"                         \
      --column="CONS/SUP" --column="nom du(des) fichier(s) de $repertoire_a_vider" \
      ${liste_fichier}                      \
           2>/dev/null `    # ne pas effacer cette ligne fin de choix
code=$?
echo "code de zenity $code"
    if [[ $code == 0 ]] # code retour zenity (0=normal,sinon clic/x  , Esc , )
    then
        [[ -n `echo $choix|grep "EXIT"` ]] && exit 0
        if [[ -z $choix ]] # $choix est vide
            then
                echo "Aucun choix effectué"
                continue # on recommence
            else
                echo "le choix est :"
                echo "$choix"
                IFS="|"
                list=($choix)
                echo "le 1er  est ${list[0]}"
                echo "le 2ème est ${list[1]}"
                echo ${list[@]}
                IFS="$OLDIFS"
                 if zenity --question --title "SUPPRESSION" \
                          --text "Suppression de ${#list[@]} fichiers" \
                          --no-wrap --ok-label "Confirmer Suppression" \
                          --cancel-label "Abandonner la Suppression"
                  then
                  for i in ${list[@]}
                    do
                       i=$(sed "s/*/ /g" <<< $i) #remettre espace à la place des *
                       echo "je supprime $repertoire_a_vider/$i"
                       rm "$repertoire_a_vider/$i"
                    done
                   fi
                
                continue # on recommence
            fi
    else 
        [[ $code == 1 ]] && continue # on a cliqué sur Re-cocher
    fi
    confirmation_sortie
done
}

function ne_commence_pas_par_begin {
# le fichier à traiter ne doit pas commencer par ### BEGIN /etc/grub.d/10_linux ###
read ligne < "$fich_source"
if [[ "$ligne" =~ ^"$deb" ]]
    then
        echo ; echo
        echo "désolé"
        echo "le fichier grub à traiter ( $fich_source )"
        echo "n'a pas le droit de commencer par la ligne"
        echo "$deb"
        echo "rappel :" 
        echo "    1- cette ligne"
        echo "       $deb"
        echo "       DOIT apparaître plus loin dans le fichier"
        echo "            même pour un fichier grub d'essai"
        echo
        echo "    2- le fichier à traiter DOIT commencer par une ligne de commentaire"
        echo "         (car cette première ligne sera modifiée)"
        echo
        echo "    3- en réel le fichier grub commence par #"
        exit 1 # au lieu de return 1
    fi
}

function trier_fichier {
echo ; echo
echo "fichier grub choisi : $fich_source"
deb="### BEGIN /etc/grub.d/10_linux ###"
fin="### BEGIN /etc/grub.d/40_custom ###"

ne_commence_pas_par_begin

# création de 3 fichiers tmp0-<date>.txt tmp1-<date>.txt tmp3-<date>.txt

[[ -e "$fich_source_0" ]] && rm "$fich_source_0" # inutile mais évite message d'erreur rm
[[ -e "$fich_source_1" ]] && rm "$fich_source_1" # inutile mais évite message d'erreur rm
[[ -e "$fich_source_2" ]] && rm "$fich_source_2" # inutile mais évite message d'erreur rm


fich="$fich_source_0"
presence_10_linux=1
IFS="~"
while read ligne
do
	case "$ligne" in
		$deb ) fich="$fich_source_1" ;  presence_10_linux=0		;;
		$fin ) fich="$fich_source_2" 							;;
	esac
	echo "$ligne" >> $fich
done < "$fich_source"
IFS="$OLDIFS"

# après lecture du fichier on a du renconter le ligne 10_linux sinon
if [[ $presence_10_linux -eq 1 ]]
then
	echo "la présence de la ligne $deb est obligatoire"
	echo "le traitement ne commence qu'à partir de cette ligne"	
	echo "ajouter cette ligne au fichier"
	exit 0
fi
	
}


function verifier_presence_dev { # dans le cas d'utilisation d'un blkid personnel
#chaque dev de la machine doit être déclaré dans le fichier manuel !!!
echo
# mettre les dev de "sudo blkid" dans un tableau
dev1=(`awk -F" " '{printf("%s ",$1)}' "$blkid"`)

# mettre les dev du fichier choisi dans un tableau
dev2=(`awk -F" " '{printf("%s ",$1)}' "$blkid_choisi"`)

manque=""
for d1 in ${dev1[@]} # /dev/sdxy: /dev/sdzt: de blkid
do
	res=`grep $d1 <<< ${dev2[@]}`
	[[ -z $res ]] && manque="$manque $d1" # si non trouvé , ajout
done
	if [[ -n $manque ]]
		then 
			echo "dans le fichier $blkid_choisi il manque"
			echo ; echo $manque ; echo
			echo "tous les dev présents sur la machine doivent être déclarés dans ce fichier"
			echo "veuillez éditer ce fichier"
			echo "format habituel dev/sdxx: LABEL=\"xxxx\"  UUID=\"xxxx\""
            echo " un caractère espace est requis devant LABEL et UUID"
            echo " UUID est obligatoire"
			echo " la présence de LABEL n'est pas obligatoire"

			exit 0
		fi
}




function modif_ligne1_grub { # récupère la première ligne et modifie en y mettant la date

res=`echo "$1" | grep "^ *	*#"`



if [[  -n $res ]] # la ligne est bien un commentaire (commence par #)
	then
		trans="#### $num : $fich_source modifié par $0 ####"
		echo $trans			> "$fich_sauv"
		((nb_lignes_cons++))
		((nb_lignes_hors_menu++))
sort_info_transforme "$1" "première ligne modifiée en" "$trans"

	else
		echo "la première ligne du fichier est "
		echo $1
		echo	
		echo "mais il faut que la première ligne du fichier"
		echo "$fich_source"
		echo "commence par un #"
		echo "ajouter cette ligne de commentaire au début de ce fichier"
		echo "arrêt du programme"
		exit 0
	fi #[[ -n $res  ]]

}


function OK {
rep=""
while [[ $rep != [oOyYnN] ]]
do
titre="programme $0"
texte="cette partie de programme supprime des lignes supposées inutiles de grub 
 - paragraphes  contenant ......$rech_dev.....$rech_dev........... AVANT la chaine $rech_class
 - menuentry n'ayant pas des UUID égaux dans la ligne search et la ligne linux
    (à partir de V34 les menuentry sur boot séparé sont conservés)

 - le programme demande le nom du fichier à traiter .. 
         ==> en réel ce devrait être <partition>/boot/gub/grub.cfg
 - le programme crée un fichier grub-OK-date qui pourra être utilisé pour remplacer le fichier grub
 - le programme utilise aussi le label des partitions ou d'un fichier de référence 
        pour informer plus précisement la ligne menuentry de grub,
        on peut utiliser un fichier de référence uuid label (au format blkid)
 
 - remarque : pour des essais , on peut traiter n'importe quel fichier ayant un format grub
     si le fichier à traiter n'est pas au format grub , il ne fonctionnera pas correctement
     et en réel il serait préférable de lancer ce programme après avoir lancé un update-grub

trois fichiers sont créés :
    grub-OK -<aaaa:mm:dd-hh:mm:ss>.txt        ( le grub reformaté )
    grub-sup-<aaaa:mm:dd-hh:mm:ss>.txt        ( les menuentry qui ont été supprimés )
    grub-mod-<aaaa:mm:dd-hh:mm:ss>.txt        ( les lignes modifiées )

    vous pourrez analyser ces fichiers pour voir ce qui s'est passé
    avant de remplacer le fichier traité (surtout si c'est grub.cfg)
    (en fin de traitement répondez alors non à la demande de remplacement
     et faites le remplacement manuellement)

lors du traitement ..... ( c'est uniquement une info visuelle )
    les  x  qui défilent indiquent des lignes de menu qui seront supprimées
    les  c  qui défilent indiquent les lignes de menu qui seront conservées
    les  .  qui défilent indiquent les autres lignes  (qui seront conservées)
    un   S  indique un début de submenu
    un   M  indique un début de menuentry
    un   m  indique la suite de menuentry 
 
            tapez O puis valider pour continuer
            tapez A puis valider pour arrêter 

            O pour continuer / A pour arrêter le programme  
       "
       
rep=`zenity --entry --title "$titre" --text "$texte" --width "800"`
case $rep in
	[oOyY]	)	:												;;
	[aA]	)	exit 1											;;
	*		) 	echo "utilisez seulement oOyYaA S.V.P."			;;
esac	
done
}


function choix_fichier_blkid { # retourne 0 si fichier blkid choisi
fichier_source=""
titre="$0               Sélectionnez le fichier contenant UUID et LABEL des partitions"
fichier_source=`zenity --file-selection --title="$titre"`
case $? in	#$? est le code de retour de zenity
 	0)	blkid_choisi="$fichier_source"						            ;;
	1)	echo "Aucun fichier UUID-LABEL sélectionné."	; exit 1	;;
	-1)	echo "Une erreur inattendue est survenue." 		; exit 1	;;	
	*)	echo "erreur non reconnue" 						; exit 1	;;	
esac
}


function critere_suppression_2 { # se fait après une initialisation de menu[0 ...n]

##### attention les codes de retour ont changé
# 0 si ligne search et ligne linux et uuid égaux (menu conservé + label dans menu[0])
# 1 si pas de ligne search ou linux              (menu conservé intégralement)
# ligne search et linux trouvées
# 3 aucun UUID trouvé dans fichier UUID-LABEL
# 2 si uuid différents                           (menu supprimé à revoir?)

uuid_search="x"
uuid_linux="y"

ligne_search=""
ligne_linux=""

# recherche dans le tableau menu[1..n] de la ligne search

#TEST

for i in ${!menu[@]}				# pour tous les indices 0..n
do
	[[ $i = 0 ]] && continue		# sauf dans menu[0]
	res=`grep "$chaine_search" <<< "${menu[i]}"` # dans menu[1..n]
	if [[ -n $res ]]
		then
			ligne_search="${menu[i]}"
			break					# 1er menu[n] trouvé est le bon
		fi

	done


if [[ -z "$ligne_search" ]]
then
	return 1 # pas de chaine search => on conservera le menu intégralement
fi

# recherche dans le tableau menu[] de la ligne linux


for i in ${!menu[@]}				# pour tous les indices 0..n
do
	[[ $i = 0 ]] && continue		# sauf dans menu[0]
	tmp=`sed 's/[[:blank:]]//g'	<<< "${menu[i]}"` #suppression des blank de menu
	res=`grep "$chaine_linux"   <<< "${menu[i]}"` # dans menu[1..n]
	if [[ -n $res ]]
		then
			ligne_linux="${menu[i]}"
			break					# 1er menu[n] trouvé est le bon
		fi

	done


if [[ -z "$ligne_linux" ]]
then
	return 1 # pas de chaine linux => menu conservé sans modif
fi

#uuid ligne search présent dans fichier de réf uuid-label ?
# si trouvé positionne uuid_search
n=-1
while [[ $n -lt $maxuuid ]]
	do
	((n++))					# recherche de uuid[0..n]
	if [[ -n ${uuid[$n]} ]] # précaution supplémentaire uuid non vide
	then
		res=`grep ${uuid[$n]} <<< "$ligne_search"`	#  y-a-t-il l'UUID
		if [[ -n $res ]] 
			then
				uuid_search=${uuid[$n]}
				break 				# le premier uuid trouvé dans blkid sera le bon
		fi
	fi 
done 


# uuid ligne linux présent dans fichier de réf uuid-label ?
# si trouvé positionne uuid_linux
n=-1
while [[ $n -lt $maxuuid ]]
	do
	((n++))					# recherche de uuid[0..n]
	if [[ -n ${uuid[$n]} ]] # précaution supplémentaire uuid non vide 
	then
		res=`grep ${uuid[$n]} <<< "$ligne_linux"`	#  y-a-t-il l'UUID
		if [[ -n $res ]] 
			then
				uuid_linux=${uuid[$n]}
				break 				# le premier uuid trouvé dans blkid sera le bon
		fi
	fi 
done

#echo;echo $LINENO $ligne_linux $uuid_linux;sleep 2
# V46 +++ on peut trouvé root=/dev/sdxy au lieu de root=UUID==
# if uuid_linux inchangé (y) , recherche uuid  par le dev , et on recherche l'uuid du
if [[ $uuid_linux = "y" ]]
then
n=-1
while [[ $n -lt $maxuuid ]]
	do
	((n++))					# recherche de uuid[0..n]
	if [[ -n ${dev[$n]} ]]  # précaution supplémentaire dev non vide 
	then
		res=`grep "${dev[$n]} " <<< "$ligne_linux "`	# /dev dans la ligne? espace pour différencier "/dev/sda1 " <<< "dev/sda10 "
#echo;echo $LINENO $res
#echo $LINENO ${dev[$n]} 
#echo $LINENO $ligne_linux
		if [[ -n $res ]] 
			then
#echo $LINENO $ligne_linux $uuid_linux;sleep 2
                uuid_linux=${uuid[$n]} # car dev et uuid ont le même indice !!!!!
				break 				   # le premier dev trouvé dans blkid sera le bon
		fi
	fi 
done
fi
#echo;echo $LINENO $ligne_linux $uuid_linux;sleep 2
# analyse des résultats

if [[ ${uuid_search}${uuid_linux} = "xy" ]]
then
	return 3 # aucun des uuid n'a été trouvé dans blkid ( peuvent être égaux ou non )
fi 

####################################################################################
# on peut avoir uuid_search  uuid_linux
#               x            1ea0....  : n'existe pas  , existe       : code retour 2
#               a04f...      y         :   existe      , n'existe pas : code retour 2
#               bcde...      fghi....  : uuids existants et différents: code retour 2
#               1234...      1234....  : uuids existants et égaux     : code retour 0
#####################################################################################



# si $uuid_search-$uuid_linux est dans UBoot on renvoie 4
# ce menu correspond à une partition avec boot séparée

for i in ${!UBoot[@]}		# pour tous les indices 0..n
do

	[[ $uuid_search-$uuid_linux = ${UBoot[$i]} ]] && return 4 

done


if [[ "$uuid_search" != "$uuid_linux" ]]
	then
		return 2 #  uuid différents on supprimera ce menu
	else
		return 0 # uuid egaux on conservera ce menu après modif de menu[0]
fi

} # fin function critere_suppression_2


function ajout_label_menuentry { # ajoute un label à menu[0] (search ou linux)
rech_uuid_label_menuentry "$1" 	# retour 0 si label trouvé , pas zéro sinon
code=$?
if [[ $code -eq 0 ]]
  then # on a un label
	  tmp=${menu[0]}	
#	  menu[0]=`sed "s/menuentry '/menuentry '$label_trouve : /" <<< ${menu[0]}`
#	  menu[0]=`sed "s/menuentry \"/menuentry \"$label_trouve : /" <<< ${menu[0]}`
#	  menu[0]=`sed "s/${label_trouve} *:* *${label_trouve}/${label_trouve}/" <<<${menu[0]}`

# 1 remplacement de l'ancien par le nouveau , (s'il n'y a pas d'ancien ,rien n'est changé)
            menu[0]=`sed "s/menuentry '.* : /menuentry '$label_trouve : /" <<< ${menu[0]}`
            menu[0]=`sed "s/menuentry \" .*: /menuentry \"$label_trouve : /" <<< ${menu[0]}`
# 2 ajout du nouveau en tête
            menu[0]=`sed "s/menuentry '/menuentry '$label_trouve : /" <<< ${menu[0]}`
            menu[0]=`sed "s/menuentry \"/menuentry \"$label_trouve : /" <<< ${menu[0]}`
# 3 suppression des doublons
            menu[0]=`sed "s/${label_trouve} *:* *${label_trouve}/${label_trouve}/" <<<${menu[0]}`






	  if [[ $tmp != ${menu[0]} ]]
		then
			sort_info_transforme "$tmp" "	LIGNE transformée en" "${menu[0]}" 
            ((nb_lignes_mod++))   # ajout V46++ 
		fi #[[ $tmp != ${menu[0]} ]]
	  fi # [[ $code -eq 0 ]]
}


function memorise_menuentry { # mémorise menuentry de submenu pour écriture ultérieure
	for  p in ${!menu[@]}	# pour tous les indices de menu[]
		do
			((i_s++))
			ligne_sousmenu[i_s]=${menu[$p]} 	# mémorise menu[0 ..n]
			((nb_lignes_menu_cons++))			# stat
		done 
}


function ecrire_lignes_memorisees { # écrit les lignes dans sauv

for p in ${!ligne_sousmenu[@]}	# pour tous les indices de ligne_sousmenu[]
	do
		echo "${ligne_sousmenu[$p]}" >> "$fich_sauv"	# écriture l_s[0..n]
		((nb_lignes_cons++))							# stat
	done
}


function traite_ligne_submenu { # reçoit $1 (ligne submenu '.......{

fin_submenu=1 # sera mise à 0 si un menuentry se termine par }  }
submenu="$1" #mise en mémoire de cette ligne

# j'utilise la mémorisation label_submenu du label d'un menuentry précédent  

if [[ -n $label_submenu ]]
then
# ajout du label et suppression double label
submenu=`sed "s/submenu '/submenu '${label_submenu} : /"   <<< $submenu`
submenu=`sed "s/submenu \"/submenu \"${label_submenu} : /" <<< $submenu`
submenu=`sed "s/${label_submenu} *:* *${label_submenu}/${label_submenu}/" <<<$submenu`
fi

i_s=0
unset ligne_sousmenu

ligne_sousmenu[0]="$submenu"	# mémorisation pour sortie finale
((nb_lignes_hors_menu++))		# ligne considérée comme hors menu

# lire les lignes qui suivent submenu jusquà trouver ligne ......} hors menuentry)

while read ligne
do
((nb_lignes_lues++))
		# si on trouve .... } hors menuentry on est au bout du submenu
		# il faut sauvegarder la ligne submenu , les lignes intermédiaires et menuentry
		# je ne traite pas du cas où on trouverait une ligne menuentry terminée par  } }
		# V28 et suivante ce cas est traité
		# une ligne menuentry terminée par } } provoque la fin du submenu  ($fin_submenu 0)

# on sort de la boucle si on trouve } en fin de ligne hors menuentry

tmp=`sed 's/[[:blank:]]//g' <<<"$ligne"` # supprime tous les blancs de la ligne

if [[ "$tmp" =~ }$ || "$fin_submenu" = 0 ]]   ### on est en fin de submenu ###
				# pas tout à fait exact
				# si on peut  avoir { ...... } hors menuentry
		then
			((i_s++))
			ligne_sousmenu[i_s]="$ligne"	# mémoriser cette ligne
			((nb_lignes_hors_menu++))		# stat
			echo -e ".\c"
			ecrire_lignes_memorisees		# écriture de ces lignes de submenu
			label_submenu=""
			return							# fin de traitement de submenu
		fi # [[ "$tmp" =~ }$ ]]

# V28 élargissement aux blancs de grep après {
res=`echo "$ligne" | grep "^[[:blank:]]*menuentry.*{[[:blank:]]*$"`
mem=`echo "$ligne" | grep "^[[:blank:]]*menuentry ['\"]Memory test.*{[[:blank:]]*$"`
#res=`echo "$ligne" | grep "^[	 ]*menuentry.*{[ 	]*$"`
#mem=`echo "$ligne" | grep "^[	 ]*menuentry ['\"]Memory test.*{[ 	]*$"`

if [[ -n $mem ]]
then			
	res=""		# si on trouve la chaine Memory pas intéressant on force res à vide
fi

if  [[ -z $res ]]
	then								# ni menuentry ..{ ni memory ...{
		((i_s++))						# 
		ligne_sousmenu[i_s]="$ligne"	# mise en mémoire pour écriture ultérieure
		((nb_lignes_hors_menu++))		# stat
		echo -e ".\c"	
	
	else
		lire_menuentry 					# menu[0..n]  et ((nb_lignes_lues++))
		trt_menu2 "${menu[0]}" 			# 1 si contient dev dev
		code_dev_dev=$?

		if [[ $code_dev_dev -eq 1 ]]	# 1 la ligne contient /dev /dev
			then
				sort_menu_1 " " "menu supprimé : trop de /dev/sd"		# suppression de ce menu
				((nb_menu_sup++))		# stat
			else 						# pas 1 : ne contient pas dev dev
				critere_suppression_2
				code_crit2=$?			# 0 1 2 3 

				case $code_crit2 in
				0)						# les uuid sont égaux modifier menu[0]
					ajout_label_menuentry "$chaine_search"
					memorise_menuentry	# mettre en mémoire ces lignes de menuentry
					((nb_menu_cons++))	# stat non prévu dans memorise_menuentry
				;;
				1)						# pas de search ni de linux on garde sans modif
					memorise_menuentry	# mettre en mémoire ces lignes de menu
sort_info_transforme "${menu[0]}" "menu dans submenu conservé (pas de ligne search ou linux)"
					((nb_menu_cons++))	# stat non prévu dans memorise_menuentry
				;;
				2)						# uuid différents on supprime ce menu
					sort_menu_1 " " "menu supprimé : uuid différents"
					((nb_menu_sup++))	# stat non prévu
				;;
				3)						# uuid non trouvé (search et linux existent)
					memorise_menuentry	# mettre en mémoire ces lignes de menu
sort_info_transforme "${menu[0]}" "menu dans submenu conservé : uuid (search ou linux) non trouvé"
					((nb_menu_cons++))	# stat non prévu
					((nb_menu_sans_uuid++))
				;;
				4)						# uuid != mais boot séparé
					# revoir pour le label
					ajout_label_menuentry "$chaine_linux"
					memorise_menuentry	# mettre en mémoire ces lignes de menuentry
					((nb_menu_cons++))	# stat non prévu dans memorise_menuentry
					((nb_menu_boot_cons++))
					
				;;					
				esac
			fi # [[ $code_dev_dev -eq 1 ]]
	fi # [[ -z $res ]]
done

# si on arrive ici il y a erreur de traitement quelque part
echo
echo " ligne bach $LINENO"
echo " erreur de format ? dans le fichier $fich_source !!!!!!!!!!"
echo " dernière ligne de menu lue :"
echo
echo ${menu[0]}
echo
echo " dernière ligne lue : $nb_lignes_lues"
echo " $ligne"
sleep 100
exit 0 
}


function rech_uuid_label_ligne { # recherche uuid et label  de $1 dans uuid[0..n]
# renvoie 0 uuid trouvé et label trouvé	uuid_trouve=xxx  label_trouve="yyy"
# renvoie 1 uuid trouvé et label vide	uuid_trouve=xxx  label_trouve=""
# renvoie 2 uuid non trouvé				uuid_trouve=""   label_trouve=""	
uuid_trouve=""
label_trouve=""
n=-1
while [[ $n -lt $maxuuid ]]
	do
	((n++))								# uuid suivant
	if [[ -n ${uuid[$n]} ]]				# précaution supplémentaire uuid non vide 
	then
		res=`grep ${uuid[$n]} <<< $1`	#  $1 est une ligne de menu
		if [[ -n $res ]] 
			then
				uuid_trouve=${uuid[$n]}
				if [[ -n ${label[$n]} ]]
				then
					label_trouve=${label[$n]}	# si label non vide positionne label_trouve
					return 0					# uuid trouvé / label non vide trouvé
				else
					return 1					# uuid trouvé / label ""
				fi
		fi
	fi 
done 
return 2										# uuid non trouvé 
}


function rech_uuid_label_menuentry { # recherche uuid et label dans la ligne $1 de menu[1 ..n]

for p in ${!menu[@]}	# pour tous les indices du tableau 0..n
do
	[[ $p = 0 ]] && continue	# mais pas dans menu[0]
	res=`echo ${menu[$p]} | grep "$1"`	
	if [[ -n $res ]]
		then
			rech_uuid_label_ligne ${menu[$p]}		# donne uuid_trouve / label_trouve
			return $?								# 0 uuid égaux 
													# 1 uuid trouvé , label vide
													# 2 pas d'uuid dans search 
		fi
	done
return 3	# pas de search trouvé , (donc pas d'uuid , et donc pas de label) !!!
}




function transforme_ligne_menuentry {	# modifie la première ligne d'un menuentry conservé
# recherche l'UUID dans la ligne search --no-floppy --fs-uuid --set=root
# si trouvé , on récupère le label
# si label vide on ne fait rien
# sinon on rajoute avec : en tête après menuentry ' ou menuentry " 
# 

label_trouve=""
uuid_trouve=""
tmp=${menu[0]}					# servira de test pour sortie si modifié
rech_uuid_label_menuentry "$1"	# positionne le label à la bonne valeur
code=$?							# retour de la fonction

case $code in
	0)		# UUID trouvé : $uuid_trouve LABEL trouvé : $label_trouve

			if [[ $label_submenu = "" ]]	# servira dans traitement d'un submenu éventuel
				then						# on memorise le premier label menuentry trouvé	
					label_submenu="$label_trouve"
				fi	
#			menu[0]=`sed "s/menuentry '/menuentry '$label_trouve : /" <<< ${menu[0]}`
#			menu[0]=`sed "s/menuentry \"/menuentry \"$label_trouve : /" <<< ${menu[0]}`
			#suppression double labels dans cette ligne
#			menu[0]=`sed "s/${label_trouve} *:* *${label_trouve}/${label_trouve}/" <<<${menu[0]}`

# 1 remplacement de l'ancien par le nouveau , (s'il n'y a pas d'ancien ,rien n'est changé)
# 2 ajout du nouveau
# 3 suppression des doublons


# 1 remplacement de l'ancien par le nouveau , (s'il n'y a pas d'ancien ,rien n'est changé)
            menu[0]=`sed "s/menuentry '.* : /menuentry '$label_trouve : /" <<< ${menu[0]}`
            menu[0]=`sed "s/menuentry \" .*: /menuentry \"$label_trouve : /" <<< ${menu[0]}`
# 2 ajout du nouveau en tête
            menu[0]=`sed "s/menuentry '/menuentry '$label_trouve : /" <<< ${menu[0]}`
            menu[0]=`sed "s/menuentry \"/menuentry \"$label_trouve : /" <<< ${menu[0]}`
# 3 suppression des doublons
            menu[0]=`sed "s/${label_trouve} *:* *${label_trouve}/${label_trouve}/" <<<${menu[0]}`









			if [[ $tmp != ${menu[0]} ]]
			then #TEST
				sort_info_transforme "$tmp" "	LIGNE transformée en" "${menu[0]}"
                #echo "$LINENO ${menu[0]} avant $nb_lignes_mod"
                (( nb_lignes_mod++ )) # ajout V46++
                #echo "après $nb_lignes_mod"
			fi
	;;
	1)		# LABEL vide #TEST
				sort_info_transforme "$tmp" "pas de label pour $uuid_trouve dans $blkid_choisi"
	;;
	2)		#LABEL vide uuid non trouvé #TEST
				sort_info_transforme "$tmp" "uuid de ligne search non trouvé dans $blkid_choisi"
	;;
	3)		# pas de ligne search trouvée dans menuentry v
				sort_info_transforme "$tmp" "ligne search non trouvée"
	;;	
	*) # ???? #TEST
				sort_info_transforme "$tmp" "code inconnu : $code"
	;;
esac

return $code
}


function lire_menuentry { # met dans tableau menu[n] jusqu'à trouvé } seul sur la ligne
unset menu
i=0
menu[0]="$ligne"								# menu[0] est la première ligne
echo -e "M\c"									# trace début de menuentry
while read ligne								# ligne suivante
do
	((i++))
	((nb_lignes_lues++))
	menu[$i]="$ligne"							# mémorisée dans menu [1 .. n]
	echo -e "m\c"								# trace écran
	tmp=`sed 's/[[:blank:]]//g' <<<"$ligne"`	# suppression des blancs pour test

	if [[ "$tmp" =~ }}$ ]]
		then
			fin_submenu=0						# termine par  }   } fin de submenu !!!
		fi

	if [[ "$tmp" =~ }$ ]]   					# la ligne se termine par } ?
		then
			return								# oui fin de menuentry
		fi
			# et si pas de ... } on ira jusqu'en fin de fichier !!!!
			# c'est un critère de format de grub
done
}

function sort_menu_0 {	# écrit menu[0..n] dans le fichier de sauvegarde

for p in ${!menu[@]}						# pour tous les indices
	do
		echo "${menu[$p]}" >> "$fich_sauv"	# écriture menu[0..n]
		((nb_lignes_cons++))				# stat
		((nb_lignes_menu_cons++))			# stat
		echo -e "c\c"						# suivi écran
	done
}


function sort_menu_1 {	# écrit menu[0..n] dans le fichier suppression

#écriture des paramètres reçus dans fich_sup
	echo "#########################"	>> $fich_sup
	for arg in "$@"		# prends $1 $2 ... $n
	do
		echo $arg		>> $fich_sup
		#echo			>> $fich_sup
	done

# écriture du menu dans fichier sup
for p in ${!menu[@]}					# pour tous les indices
do
	echo "${menu[$p]}" >> "$fich_sup"	# écriture menu[0..n]
	((nb_lignes_sup++))					# stat
	echo -e "x\c"						# suivi écran
	done
}



function sort_info_transforme { # écrit les paramètres reçus fich_transforme

	echo "#########################"	>> $fich_transforme
	for arg in "$@"	# ( $1 $2 ... $n )
		do
			echo $arg		>> $fich_transforme
			#echo			>> $fich_transforme
		done
}


function trt_menu2 { # analyse le paramètre $1
	# renvoie 1 si $1 contient plus d'une fois /dev/sd  avant --class (suppresion)
	# renvoie 0 sinon

IFS="$OLDIFS"		# il faut l'espace comme délimiteur
tableau=($1)	# mise en tableau de la ligne
IFS="~"		# peut-être utile pour la suite ?

nbdevsd=0 					# nombre de fois que l'on trouve /dev/sd (avant --class)

for n in ${!tableau[@]} # de 0 1 2 .... x
do
	r_class=`echo ${tableau[$n]} | grep "$rech_class"`	# test présence --class
	if [[  -n $r_class ]] 								# --class ou pas ?
		then
			break				# --class est trouvé, sort de la boucle for
		else
			r_dev=`echo ${tableau[$n]} | grep "$rech_dev"`   #  test présence /dev/sd
			if [[ -n $r_dev ]]
				then
					((nbdevsd++))							# incrémente si on a /dev/sd 
					if [[ $nbdevsd -gt 1 ]]					# si plus d une fois /dev/sd
						then
							return 1 						# on sort en renvoyant 1
						fi #[[ $nbdevsd -gt 1 ]]
				fi #[[ -n $r_dev ]]
		fi #[[  -n $r_class ]]
done

if [[ $nbdevsd -gt 1 ]]	# test nombre
	then
		return 1 # 1 si plus d'une fois /dev/sd
	else
		return 0 # 0 sinon
fi
}



#trt=0;((trt++));echo "début de traitement $trt - $LINENO";read g


# début du programme ##################################################################################
######### variables ################################### 
OLDIFS="$IFS"               # sauvegarde IFS
rech_class="\-\-class"		# jusqu'à trouver la chaine --class dans menuentry
rech_dev="\/dev\/sd"		# la présence de la chaine  /dev/sd dans menuentry

                            # ne pas modifier le nom des fichiers suivants 
blkid="blkid-res.txt"       # (fichier contenant le résultat de sudo blkid)
fich_fstab_conc="UBoot-UPart.txt" # créé par recup-fstab contient les uuid ayant boot séparé

blkid_choisi=""	            # fichier personnel choisi contenant dev-label-uuid
chaine_search="search \-\-no\-floppy \-\-fs\-uuid \-\-set=root"
	 						# (un tiret doit être protégé par \ pour une recherche dans grep)
chaine_linux="linux.*\/vmlinu" 			# + général "linux......./vmlinu"
label_submenu=""						# label valide du menuentry précédent

ZZZnum="ZZZnum"         # le répertoire qui contiendra les fichiers temporaires xxxx-$num
prg="$nom_dir/recup_fstab_V8"	# création de $fich_fstab_conc (UBoot_UPart.txt)
#########################################################
num=`date +%Y:%m:%d`-`date +%H:%M:%S`



# ces 3 variables seront re-précisées en utilisant le nom complet du fichier grub traité
fich_sauv=""        
fich_sup=""
fich_transforme=""

fich_source_0="$ZZZnum/tmp0-$num.txt" # lignes de 1 à 10_linux[
fich_source_1="$ZZZnum/tmp1-$num.txt" # lignes de [10_linux à 40_custom[
fich_source_2="$ZZZnum/tmp2-$num.txt" # lignes de [40_custom à la fin]

##### pour les stat #####################################
fich_stat="$ZZZnum/stat-$num.txt"
nb_menu_cons=0
nb_menu_boot_cons=0
nb_menu_sup=0
nb_menu_sans_uuid=0
nb_lignes_sup=0
nb_lignes_cons=0
nb_lignes_lues=0
nb_lignes_hors_menu=0
nb_lignes_menus_cons=0
nb_lignes_mod=0        # ajout V46++
#########################################################




! [[ -e "$ZZZnum" ]] && mkdir "$ZZZnum" # pourrait être mis plus loin

#((trt++));echo "début de traitement $trt - $LINENO";read g


#si le programme $prg (recup_fstab_Vx) n'existe pas on sort
# voir pour utiliser getopts
# deux façons de lancer ce programme
# - en terminal  avec ou sans l'option --sansfstab
# - clic sur le fichier (sans l'option --sansfstab) 
case "$1" in
    --sansfstab )
            echo "
            Rappel :
                un fichier à jour au format blkid
                (dev  - uuid  - label éventuel) 
                est nécessaire au bon déroulement du programme

                s'il y a des OS avec boot séparés
                un fichier
                $fich_fstab_conc à jour
                est nécessaire (il est créé par recup_fstab)
                (ce fichier donne l'uuid de la partition de boot
                        associé à l'uuid de la partition système)

                en cas de doute utilisez 

                $0 sans le paramètre --sansfstab
                pour re-créer correctement ce fichier

            Taper sur Entrée pour continuer Ctrl C pour arrêter"
            #touch $fich_fstab_conc # création artificielle du fichier
            read g
             code=0            ;;
	*  )
        ! [[ -e "$prg" ]] && echo "fichier $prg de récup. (fstab et blkid)  manquant" && read g && exit 0
        echo "$0 lance le programme $prg"
        $prg "$ZZZnum"
        code=$?
        ;;
esac 
echo "le code de retour est $code" 

((trt++));echo "début de traitement $trt $LINENO"



if [[ $code -ne 0 ]]
	then
		echo "  il y a eu un problème de traitement du programme  $prg"
		echo "  si l'arrêt n'est pas volontaire"
		echo "  vérifier que le répertoire /mnt/jpb ne comporte pas des résidus de fichiers"
		echo "  éventuellement faire le ménage dans ce répertoire"
		read g
		exit 0
	fi
echo
echo "suite du programme $0"
echo ; echo

# pour les fichiers temporaires -$num




if ! [[ -e $fich_fstab_conc  ]]	# UBoot_UPart a normalement été créé par recup_fstab
	then
		echo "le fichier  $fich_fstab_conc est introuvable"
		echo "il faut d'abord exécuter $prg" 
		echo "ou mettre à disposition manuellement un fichier $fich_fstab_conc"
		echo ; echo ; read g
		exit 0
	else  
		echo "  vérification des uuid correspondants à des systèmes sur boot séparés"
		echo "  couples uuid-boot - uuid-systeme des menuentry en boot séparé"
		echo
		echo "###### contenu du fichier $fich_fstab_conc #############################"
		cat $fich_fstab_conc
		echo "#######################################################################"
		echo
		echo "  vérifier visuellement le contenu des lignes comprises entre les ###"
		echo "  il existe deux lignes par couple (ou rien)"
		echo "          une ligne uuid1-uuid2"
		echo "          une ligne uuid2-uuid1"
        echo
		echo "  tapez sur entrée pour continuer"
		read g
	fi

# lecture et mise en mémoire des infos donnée par le fichier $fich_fstab_conc ("UBoot_UPart.txt")
#################################################################################################
max_boot=-1
while read l_boot
do
	[[ -z $l_boot ]] && echo "ligne vide je passe" && continue		# si ligne vide ou commentée
	[[ $l_boot =~ ^[[:blank:]]*# ]] && echo "ligne commentée $l_boot je passe" && continue
	((max_boot++))
	echo $l_boot
	UBoot[$max_boot]=$l_boot # format uuid1-uuid2 à la suite
done < $fich_fstab_conc
#################################################################################################

OK # présentation du programme

code=1
while [[ $code = 1 ]]
do
rep=""
texte_supplementaire=""
if ! [[ -e "$blkid" ]]
	then
		texte_supplementaire="=====> !!!!! Attention ce fichier $blkid n'est pas présent !!!!!!"
	fi

while [[ $rep != [oOyYaAcC] ]]
do
titre="     Utilisation des UUID et LABEL des partitions des disques"
texte="     Choix du fichier de références  LABEL et UUID
	répondez par
			(oOyY)   si vous voulez ré-utiliser le fichier $blkid
                         ce fichier a été créé précédemment par $prg
						(contient les labels utilisés pour mettre à jour le grub
						 seront alors ceux déclarés sur la partition)
                     $texte_supplementaire

			(cC)     permet de choisir un fichier de référence UUID LABEL
						(les labels utilisés pour mettre à jour le grub
						 seront alors ceux déclarés dans ce fichier de référence)

			!!!!!	mais toutes les partitions devront être déclarées
                    le champ /dev/sdxx en premier
                    le champ LABEL="xxxxxx" non obligatoire (mais alors
                                   le menu de GRUB ne sera pas modifié pour ce dev)
                    le champ UUID="xxxxxx" (OBLIGATOIRE pour un traitement correct)
                    le champ type TYPE="xxxxx" est conseillé
                    une ligne sera donc de la forme
/dev/sdxx LABEL=\"un label correct\" UUID=\"un uuid correct\" TYPE=\"le type correspondant\"

                    ce choix peut servir si vous ne voulez pas labelliser les
                    partitions mais mettre quand même un label dans grub
                    ou bien pour effectuer des essais
                    (ce choix un peu tordu est un peu difficile à comprendre ?)

                    !!!!	en cas de doute utilisez le choix oOyY 	puis Valider

                    O pour réutilisation du fichier $blkid 
                    C pour choisir un fichier de référence UUID LABEL personnel
                    A Arrêter"
rep=`zenity --entry --title "$titre" --text "$texte" --width "800"`

case $rep in
	[oOyY]	) blkid_choisi="$blkid"; echo "utilisation du fichier créé précédemment)" ;;
	[aA]	) echo "arrêt du programme" 		; exit 0				;;
	[cC] 	) echo "choix du fichier des uuid" 	; choix_fichier_blkid 	;;
	*		) echo "utilisez seulement oO yY aA cC S.V.P."				;;
esac
done


# si le fichier de concordance n'existe pas sortie 

if ! [[ -e "$blkid_choisi" ]]
	then
		echo ; echo
		echo " $0 n'a pas trouvé le fichier"
		echo " $blkid_choisi"
		echo " que vous avez choisi comme référence UUID-LABEL"
		echo " Modifier votre choix de fichier"
		echo "    ou bien mettez à disposition ce fichier pour continuer" 
		echo ; echo ; sleep 2
	else
		code=0
	fi

done	# sors de la boucle uniquement si code=0



# récupératon dev label UUID dans des tableaux
unset dev
unset uuid
unset label
unset bdev	# à partir de V31 pour boot séparé
unset btype # le type de la partition
unset bmont # point de montage à cause du boot séparé

############## récupération dev label uuid btype dans le fichier choisi ###################
maxuuid=-1
while read ligne
do

	[[ -z $ligne ]] && echo "ligne vide je passe" && continue		# correction ligne vide
    [[ "$ligne" =~ ^[[:blank:]]*#.*$ ]] && continue                 # autorise ligne commentée
    ligne=${ligne##[[:blank:]]}                                     # suppression des [[:blank:]] au début
     echo "=>$ligne<= =>$(grep "^\/dev" <<< "$ligne")<="
     res=$(grep "^\/dev" <<< "$ligne")
     if [[ -z $res ]]
        then
            zenity --info --title="$blkid_choisi" --text="ligne $maxuuid la ligne \n $ligne \n ne commence pas par \/ \n c'est interdit" --width=500  && /
            exit 0                                                  # arrêt si une ligne ne commence pas par /
     fi
	((maxuuid++))
	# d'abord le dev
    DEV=$(awk -F":" '{print $1}' <<< "$ligne") # donne aussitôt /dev/sda1
    DEV=${DEV%%[[:blank:]]*}                   # supprime les [[:blank:]] en fin de dev (cas saisie manuelle)

    # pour les autres , à cause d'espaces possibles (dans le label)
    # et il faut mettre un espace avant pour chaque cas LABEL et non PARTLABEL UUID et non PARTUUID ...

    if grep " LABEL" <<< "$ligne"
        then
            LABEL=$(echo "$ligne"|sed -r 's/.*\bLABEL="([^"]+)".*/\1/')
        else
            LABEL=""
            echo "pas de LABEL"
        fi
  
    
    if grep " UUID" <<< $ligne
        then
            UUID=$(echo "$ligne"|sed -r 's/.*\bUUID="([^"]+)".*/\1/')
        else
            UUID=""
            echo "pas d'UUID"
        fi
        
    if grep " TYPE" <<< $ligne
        then        
            TYPE=$(echo "$ligne"|sed -r 's/.*\bTYPE="([^"]+)".*/\1/')
        else
            TYPE=""
            echo "pas de type"
        fi
    
	[[ -z `grep "^\/dev" <<< $DEV` ]] && echo \
		&& echo "il manque /dev dans la ligne $ligne du fichier de référence UUID-LABEL" \
		&& exit 0
  
	dev[maxuuid]=$DEV			#dev,label,uuid,type dans des tableaux de la ligne
	label[maxuuid]="$LABEL"
	uuid[maxuuid]="$UUID"
	btype[maxuuid]="$TYPE"

done < $blkid_choisi

##############################################################################
if [[ "$blkid_choisi" != "$blkid" ]]
then
	verifier_presence_dev # vérifie que tous les dev du fichier choisi sont bien déclarés
fi
###############################################################################
# sortie des uuid label pour info
		[[ -e "tmp-u-l.txt" ]] && rm "tmp-u-l.txt"
echo
		p=0
		while [[ $p -le $maxuuid ]]
		do
			aff_dev="${dev[$p]}"		&& [[ -z "$aff_dev"		]]	&& aff_dev="_"
			aff_label="${label[$p]}"	&& [[ -z "$aff_label"	]]	&& aff_label="___"
			aff_uuid="${uuid[$p]}"		&& [[ -z "$aff_uuid"	]]	&& aff_uuid="___"
			aff_btype="${btype[$p]}"	&& [[ -z "$aff_btype"	]]	&& aff_btype="___"

# car si l'un des $ est "" , il y a erreur d'affichage

			printf "%02s %-10s UUID %-36s LABEL: %-20s  TYPE : %-10s\n" \
					"$p" "$aff_dev" "$aff_uuid" "$aff_label" "$aff_btype"  | tee -a tmp-u-l.txt
			((p++))											
		done

titre="Affichage des concordances LABEL <=> UUID      Visualiser puis  Valider pour continuer"
zenity --text-info --title "$titre" --filename "tmp-u-l.txt" --height "640" --width "1280" --font "Courier New Bold 10"
code=$?
[[ -e "tmp-u-l.txt" ]] && rm "tmp-u-l.txt" # supprime ce fichier devenu inutile
if [[ $code -ne 0 ]]
	then
		echo $code
		exit 0 #sortie si on ne valide pas
	else
		echo $code
	fi

################ début de traitement du fichier GRUB ###############################

# Quel fichier grub traiter ?
titre="$0               Sélectionnez le fichier GRUB à traiter"
fich_source=`zenity --file-selection --filename="../fichier-grub/*" --title="$titre"`
case $? in	# $? est le code de retour de zenity
	0)	:														;;
	1)	echo "Aucun fichier sélectionné."			; exit 1	;;
	-1)	echo "Une erreur inattendue est survenue."	; exit 1	;;	
	*)	echo "erreur non reconnue"					; exit 1	;;	
esac

# $fich_source est de la forme /media/SH/grub/fichier-grub/grub-2UUID.cfg

# servira à préciser les fichiers grub-OK,grub-sup
precision=$(sed 's/\//-/g' <<< "$fich_source") # remplace les / par des -
# /media/SH/grub/fichier-grub/grub-2UUID.cfg
# precision devient -media-SH-grub-fichier-grub-grub-2UUID.cfg

fich_sauv="$ZZZnum/grub-OK-$num$precision.txt"
fich_sup="$ZZZnum/grub-sup-$num$precision.txt"
fich_transforme="$ZZZnum/grub-mod-$num$precision.txt"
 

#### lecture et traitement du fichier GRUB #######

trier_fichier # création des 3 fichiers de 1 à 10 linux 10 linux à 40 custom 40 custom à la fin 

################# traitement jusqu'à 10_linux #####################
IFS="~"
prem=0
while read ligne
do 
((nb_lignes_lues++))
if  [[ $prem -eq 0 ]]
	then
				modif_ligne1_grub "$ligne" ; ((prem++))
	else
				echo $ligne >> "$fich_sauv"
				((nb_lignes_cons++))
				((nb_lignes_hors_menu++))

fi
done < "$fich_source_0"

################# traitement de 10_linux à 40_custom


while read ligne
do
((nb_lignes_lues++))

if  [[ $prem -eq 0 ]] # pourrait être supprimé depuis V34
	then
				modif_ligne1_grub "$ligne" ; ((prem++))
	else
				# entre les crochets on a tab et espace élargisement après {
	res=`echo "$ligne" | grep "^[[:blank:]]*menuentry.*{[[:blank:]]*$"`
	mem=`echo "$ligne" | grep "^[[:blank:]]*menuentry ['\"]Memory test.*{[[:blank:]]*$"`
#	res=`echo "$ligne" | grep "^[	 ]*menuentry.*{[ 	]*$"`
#	mem=`echo "$ligne" | grep "^[	 ]*menuentry ['\"]Memory test.*{[ 	]*$"`

	# res est vide s'il n'y a pas menuentry {
	# mem est non vide si on a Memory test -ne pas traiter menuentry 'Memory test

	if [[ -n $mem ]]
	then			# si Memory test on force res à vide
		res=""
	fi

	if  [[ -z $res ]]
		then 											# pas menuentry 
			subm=`echo "$ligne" | grep "^[[:blank:]]*submenu.*{[[:blank:]]*$"`
#			subm=`echo "$ligne" | grep "^[	 ]*submenu.*{[ 	]*$"`
			if [[ -z $subm ]]
				then 									# pas menuentry pas submenu
					echo "$ligne" >> $fich_sauv			# écriture de cette ligne dans sauv
					((nb_lignes_cons++))				# stat
					((nb_lignes_hors_menu++))			# stat
					echo -e ".\c"						# trace écran
				else 									# contient submenu
					echo -e "S\c"						# trace
					traite_ligne_submenu "$ligne"		# traitement de submenu
			fi
		
		else								# on a menuentry
			lire_menuentry					# mettre en mémoire dans menu[0..n]
			trt_menu2 "${menu[0]}" 			# rem : 1 si /dev/sd /dev/sd
			code_dev_dev=$?
			if [[ $code_dev_dev -eq 1 ]]	# si 1 on supprime
				then						# le bloc menuentry contient /dev /dev
					sort_menu_1	" " "menu supprimé : trop de /dev/sd"	# fich_sup
					((nb_menu_sup++))

				else  						# menuentry ne contient pas /dev/sd /dev/sd
					critere_suppression_2	# analyse des uuid et recherche de label
					code_crit2=$?
					case $code_crit2 in
					0)						# les uuid sont égaux
						transforme_ligne_menuentry "$chaine_search"	# mettre un label dans menu[0]
						sort_menu_0					# écrire le menu dans fich_sauv
						((nb_menu_cons++))			# stat
					;;
					1)						# menu sans modif (ni search ni linux)
						sort_menu_0					# écrire le menu dans fich_sauv
sort_info_transforme "${menu[0]}" "menu conservé (pas de ligne search ou linux)"
						((nb_menu_cons++))			# stat
					;;
					2)						# uuid différents on supprime ce menu
						sort_menu_1	" " "menu supprimé : uuid différents"	# écrire dans fich_sup
						((nb_menu_sup++))				# stat
					;;
					3)						# uuid non trouvé (search et linux existent)
						sort_menu_0					# écrire le menu dans fich_sauv
sort_info_transforme "${menu[0]}" "menu conservé : UUID search ou linux non trouvé dans $blkid_choisi"
						((nb_menu_cons++))			# ce menu étant conservé
						((nb_menu_sans_uuid++))
					;;
					4)						# uuid != mais boot séparé
						transforme_ligne_menuentry "$chaine_linux" # met label dans menu[0]
						sort_menu_0					# écrire le menu dans fich_sauv
						((nb_menu_cons++))	# stat non prévu dans memorise_menuentry
						((nb_menu_boot_cons++))
					;;
					esac

				fi # [[ $code_dev_dev -eq 1 ]]
		fi #[[ -z $res ]]
	fi #[[ $prem -eq 0 ]]
done < "$fich_source_1"



echo $nb_lignes_lues

################# traitement 40_custom à fin #####################
if [[ -e "$fich_source_2" ]] # en cas d'essai sans ligne 40_custom
	then
		while read ligne
		do 
			((nb_lignes_lues++))
			((nb_lignes_cons++))
			((nb_lignes_hors_menu++))
			echo $ligne >> "$fich_sauv"
		done < "$fich_source_2"
	fi
#################################################################
IFS="$OLDIFS"

echo "###################################################################"   | tee -a "$fich_stat"
printf "%-40s %s\n" "fichier traité"              " : "                      | tee -a "$fich_stat"
echo "$fich_source"                                                          | tee -a "$fich_stat"
printf "%-40s %s\n" "le résultat se trouve dans"  " : "                      | tee -a "$fich_stat"
echo "$fich_sauv"                                                            | tee -a "$fich_stat"  
echo                                                                         | tee -a "$fich_stat"
printf "%-39s %s %5d\n" "nombre de lignes lues"      " : " "$nb_lignes_lues" | tee -a "$fich_stat"
printf "%-40s %s %5d\n" "lignes conservées"          " : " "$nb_lignes_cons" | tee -a "$fich_stat"
printf "%-40s %s %5d\n" "lignes supprimées"          " : " "$nb_lignes_sup"  | tee -a "$fich_stat"
printf "%-40s %s %5d\n" "lignes modifiées"           " : " "$nb_lignes_mod"  | tee -a "$fich_stat"   # ajout V46++
if [[ $nb_lignes_sup -gt 0 ]]
	then
printf "%-40s %s\n" "fichier des lignes supprimées"  " : "                   | tee -a "$fich_stat"
echo "$fich_sup"                                                             | tee -a "$fich_stat"
	echo                                                                     | tee -a "$fich_stat"
	fi
printf "%-40s %s %5d\n" "nombre de menus conservés"           " : " "$nb_menu_cons" | tee -a "$fich_stat"
printf "%-40s %s %5d\n" "nombre de menus supprimés"           " : " "$nb_menu_sup" | tee -a "$fich_stat"
printf "%-40s %s %5d\n" "nombre de menus avec boot conservés" " : " "$nb_menu_boot_cons" | tee -a "$fich_stat"
if [[ $nb_menu_sans_uuid -gt 0 ]]
	then
printf "%-40s %s %5d\n" "nombre de menus sans uuid trouvé" " : " "$nb_menu_sans_uuid" | tee -a "$fich_stat"
	fi
echo                                                                                  | tee -a "$fich_stat"
printf "%-40s %s %5d\n" "lignes conservées (hors menu)" " : " "$nb_lignes_hors_menu"  | tee -a "$fich_stat"
printf "%-40s %s %5d\n" "lignes conservées (menu)" " : " "$nb_lignes_menu_cons"       | tee -a "$fich_stat"
echo "###################################################################"            | tee -a "$fich_stat"

echo "après avoir vérifié manuellement le fichier"
echo "$fich_sauv"
echo "en réel vous pourrez remplacer grub.cfg à vos risques et périls"
echo                                                                     | tee -a "$fich_stat"

texte_attention=""
if [[ $fich_source =~ /boot/grub/grub.cfg$ ]]
then
    texte_attention_grub_reel="====> Attention vous avez choisi de traiter un fichier grub réel
        /boot/grub sera remplacé par le fichier résultant ... prenez vos précautions
         mais je rapelle qu'une sauvegarde du grub original est effectué
         donc récupérable"
fi



rep=""
while [[ $rep != [oOyYnN] ]]
do

################ mise à jour du fichier traité  ou non ###########################
titre="    ################       remplacement de GRUB    ###########"
texte="
        Voulez-vous remplacer le fichier choisi
                $fich_source
        par le nouveau fichier généré
               $fich_sauv
	
                 par précaution si vous répondez oui le fichier
    $fich_source (fichier original choisi)
                 sera sauvegardé dans
    $fich_source-$num
                 puis
    $fich_source 
	             sera remplacé par le contenu du fichier
    $fich_sauv

       
    $texte_attention_grub_reel

    répondez par (oOyYnN)"

rep=`zenity --entry --title "$titre" --text "$texte" --width "800"`
case $rep in
	[oOyY] )	# sauvegarde de "grub" , je conserve $num	
        echo "
        vous avez demandé le remplacement du fichier
        OK mais avant je sauvegarde le fichier original
        $fich_source
        dans 
        $fich_source-$num
        (mot de passe administrateur requis)
        sudo cp "$fich_source" "$fich_source-$num""
 			
            sudo cp "$fich_source" "$fich_source-$num"
			code=$?
			if [[ $code != 0 ]]
				then
					echo "il y a eu un problème lors de la sauvegarde du fichier
                         (code erreur : $code)"
					suppression_fichiers_temporaires
                    echo "je sors"
					exit 0
				fi

			#et fich_sauv remplace grub
            echo "
        OK je remplace
        $fich_source
        par
        $fich_sauv
        (mot de passe administrateur requis)
        sudo mv "$fich_sauv" "$fich_source"" 
        sudo mv "$fich_sauv" "$fich_source"
			code=$?
			if [[ $code != 0 ]]
				then
                    echo "il y a eu un problème lors du remplacement du fichier $fich_source
                         (code erreur : $code)"
                    suppression_fichiers_temporaires
                    echo "je sors"    
					exit 0
                else
                    echo
                    echo "fichier $fich_source remplacé"
				fi			

	;;
	[nN]	)	
             echo ; echo "fichier oiginal non remplacé"
             echo " mais le fichier résultant"
             echo " $fich_sauv"
             echo " est à disposition"
	;;
	*	) 	echo "utilisez seulement oOyYnN S.V.P."
	;;
esac
done
suppression_fichiers_temporaires
echo "taper entrée pour terminer"
read g #pour attendre
exit 0

Dernière modification par ar barzh paour (Le 22/04/2020, à 15:37)


PC          : B760M DS3H DDR4,  12th Gen Intel(R) Core(TM) i3-12100, RAM DDR4 8GiB -2400 Ubuntu 20.04, 22.04, 24.04 (en test )
Portable1 : ThinkPad P50 I7-6820HQ, 16G0 Ram Ubuntu 22.04 Ubuntu 24.04 , W10-PRO( en voyage )
Portable2 : T5750  @ 2.00GHz RAM 1GiB DDR2 667 Mhz Ubuntu 20.04 ( batterie HS )
stourm a ran war bep tachenn (Angela Duval) ( Je combats sur tous les fronts )

Hors ligne

#179 Le 16/04/2020, à 16:30

ar barzh paour

Re : [Projet terminé] correction anomalie de grub

le fichier recup_fstab_V8

#!/bin/bash
# V8+ 2020 ajout de espace (grep " LABEL" au lieu de "LABEL" et les autres ) dans recup label uuid type 
# V8  2018-11-23 utilisation de sed -r 's/.*\bLABEL="([^"]+)".*/\1/'
# V1 récupère le contenu des fichiers fstab qui peuvent exister sur la machine
# comment ?
# récupération des dev présents par blkid
# création du fichier blkid-res.txt
# pour les partitions déjà montées (via mount)
# lecture et traitement de <partition>/etc/fstab

# et pour chacune des autres partitions
# montage
# lecture et traitement de <point de montage>/etc/fstab
# démontage

# le traitement consiste à écrire dans le fichier DevSd_UBoot_UPart.txt
# pour chaque partition qui sera reconnue comme ayant un boot séparé
# DevSd="/dev/sdxx" UPart="uuid de la partition avec boot" UBoot="uuid du boot" 

# le traitement consiste à écrire dans le fichier DevSd_Uboot_Upart-date.txt
# pour chaque partition qui sera reconnue comme ayant un boot séparé
# DevSD="/dev/sdxx" UBoot="uuid du boot" UPart="uuid de la partition avec boot"

# V2 création fichier UBoot_UPart contenant les uuid d'un système avec boot séparé
# format uuid1-uuid2 et uuid2-uuid1 servira lors du traitement modif-grub

# V3 remise en forme
# V4 supprime aussi les fichiers inutiles
# les fichiers créés sont
#                   UBoot-Upart.txt         blkid-res.txt
# et dans ZZZnum :  UBoot_Upart-<date>.txt  DevSd_UBoot_UPart-<date>.txt  
  
# V5 pour des raisons d'affichage , les _ des noms de fichiers sont remplacés par des -
# V6 2018/02 vérifie les doublons label et uuid

function OK {
# à cause de problème d'affichage
#declare ffich_fstab_conc=$(sed "s/[_ ]/*/g" <<< $fich_fstab_conc)
#declare fres_blkid=$(sed "s/[_ ]/*/g" <<< $res_blkid)
#declare ffich_fstab_long=$(sed "s/[_ ]/*/g" <<< $fich_fstab_long)
#declare ffich_recup=$(sed "s/[_ ]/*/g" <<< $fich_recup)
reponse=""
while [[ $reponse != [oOyYnN] ]]
do
titre="programme $0"
texte="
    sous programme $0
    
    0- ===> il est préférable pour un résultat plus correct 
       de partir d'un fichier grub.cfg tout neuf
       donc auparavant , lancer un sudo update-grub
       
    1-le but principal de ce sous programme est de créer un fichier
        $fich_fstab_conc
    qui contiendra les uuid des systèmes qui ont un boot séparé

    2-il met a disposition le fichier
        $res_blkid
    qui contient le résultat de la commande sudo blkid

    3-il crée aussi (pour info d'analyse) le fichier
        $fich_fstab_long
    qui contient le fichier $fich_recup des partitions présentes

    comment ?
    - récupération des dev existants par sudo blkid

    - pour les partitions déjà montées (via mount)
            lecture et traitement de <partition>/etc/fstab

    - pour chacune des partitions non montées (sauf ntfs , swap)
        montage
            lecture et traitement de <point de montage>$fich_recup
        démontage

            SOUS-PROGRAMME RECUP DE MODIF GRUB
            tapez O puis valider pour continuer
            tapez A puis valider pour arrêter

            O pour continuer / A pour arrêter le programme"
       
reponse=`zenity --entry --title "$titre" --text "$texte" --width "800"`
case $reponse in
	[oOyY]	)	:                                          ;;
	[aAnN]	)	exit 1                                     ;;
	*		) 	echo "utilisez seulement oOyYaAnN S.V.P."  ;;
esac	
done
}



# affiche le fichier des doublons trouvés et demande s'il faut continuer ou non
function continuer {
titre="$1"
texte="
$(cat $fich_double_label_uuid)

    Continuer quand même ? Répondez par : (oOyYnNaA)       "
reponse=""
while [[ $reponse != [oOyYnNaAcC] ]]
do
reponse=`zenity --entry --title "$titre" --text "$texte" --width "800"`
case $reponse in
	[oOyY]	)	:                                               ;;
	[aAnN]	)	exit 65	                                        ;;
	*		) 	echo "utilisez seulement oOyYaAnN S.V.P."       ;;
esac
done	
}



function rech_uuid_dev { # si $1 est dans dev[] renvoi l'uuid correspondant
for i in ${!dev[@]}
do
	[[ "$1" = ${dev[$i]} ]] && uuid=${uuid[$i]} && break
done
}

function rech_uuid_label { # si $1 est dans label[] renvoi l'uuid correspondant
for i in ${!dev[@]}
do
	[[ "$1" = ${label[$i]} ]] && uuid=${uuid[$i]} && break
done
}


function ecrit_uuid1_uuid2 {  # recoit $1 $2 sous la fore UUID= ou LABEL= ou /dev/sdxx
# écrit uuid1-uuid2 et uuid2-uuid1 dans $fich_fstab_conc
# en remplacant le label ou le /dev/sdxx par l'uuid correspondant
# et en enlevant UUID= et LABEL=
uuid1=""
uuid2=""

echo "fonction ecrit_uuid1_uuid2 $1 $2"

#pour le premier paramètre
debut=`echo "$1" | cut -c1-5`
uuid=""
case "$debut" in
		\/dev\/ )
			rech_uuid_dev "$1" # /dev/sdxx on recherche l'uuid correspondant
			uuid1="$uuid"
		;;
		UUID\= )
			uuid1=`echo "$1" | cut -c6-` 			# si UUID= on prend ce qui se trouve après = 
		;;
		LABEL )
			rech_uuid_label `echo "$1" | cut -c7-`	# si LABEL on prend ce qui se trouve après = 
			uuid1="$uuid"							# et on recherche l'uuid correspondant
		;;
esac

#même chose pour le deuxième paramètre
debut=`echo "$2" | cut -c1-5`
uuid=""
case "$debut" in
		\/dev\/ )
			rech_uuid_dev "$2" # /dev/sdxx on recherche l'uuid correspondant
			uuid2="$uuid"
		;;
		UUID\= )
			uuid2=`echo "$2" | cut -c6-`			# UUID= on prend ce qui se trouve après = 
		;;
		LABEL )
			rech_uuid_label `echo "$2" | cut -c7-`	# LABEL on prend ce qui se trouve après =
			uuid2="$uuid"							# et on recherche l'uuid corespondant
		;;
esac

if [[ -n $uuid1 ]] && [[ -n $uuid2 ]]
then
# on écrit les deux combinaisons possibles , plus simple à traiter ensuite
echo $uuid1-$uuid2		>> $fich_fstab_conc
echo $uuid2-$uuid1		>> $fich_fstab_conc
fi

echo "fin de fonction ecrit_uuid1 uuid2 =1=>$uuid1<=== =2=>$uuid2<==="
}



function ecrit_ligne_court {	# si $3 (UBoot) non vide
								# uuid1-uuid2 dans UBoot_UPart

if [[ -n "$3" ]]			    # si uboot non vide
	then
		ecrit_uuid1_uuid2 "$2" "$3" # envoie uuid de partition et uuid de boot
	fi
}


function trans_ligne_fstab { # récupère les champs d'une ligne
# champ1 champ2 champn mais on ne s'intérese qu'aux champs 1 et 2

# champ1 : UUID=uuid ou LABEL=label ou le dev [non traités : PARTUUID= PARTLABEL=]
# champ2 : le point de montage

champ1=`echo "$1"|awk -F" " '{printf ("%s",$1)}'`	# bloc spécial ou système de fichiers distant à monter	
champ2=`echo "$1"|awk -F" " '{printf ("%s",$2)}'`	# c'est le point de montage

case "$champ2" in
		\/ )
			dev_part=$champ1	# si champ2 est /     on positionne dev_part sur champ1
		;;
		\/boot )
			dev_boot=$champ1	# si champ2 est /boot on positionne dev_boot sur champ1
		;;
esac
}

# début du programme
echo "début de programme $0 "

if [[ $# -eq 0 ]]
	then
		echo "sans le paramètre répertoire"
		ZZZnum="ZZZnum"
	else
		echo "avec le paramètre répertoire $1"
		ZZZnum="$1" # modif_grub doit envoyer ZZZnum
	fi	

echo "Répertoire : "$ZZZnum

! [[ -e "$ZZZnum" ]] && mkdir "$ZZZnum"
 
#########################################################################################
# variables
                 num=`date +%Y:%m:%d`-`date +%H:%M:%S`
           res_blkid="blkid-res.txt"				# résultat de sudo blkid
     fich_fstab_long="$ZZZnum/DevSd-UBoot-UPart-$num.txt"	# résultant commenté
     fich_fstab_conc="UBoot-UPart.txt"				# résultant concaténé UUID1-UUID2
 fich_fstab_conc_num="$ZZZnum/UBoot-UPart-$num.txt"	# sauvegarde,à supprimer manuellement
             rep_mnt=/mnt/jpb-$num					# répertoire pour montages/démontages
          fich_recup=/etc/fstab						# fichier à récupérer dans part.
fich_double_label_uuid="$ZZZnum/doublon.txt"        # contient les label ou uuid truvés plusieurs fois
#########################################################################################


OK 								# présentation du programme  / sortie ou non

reponse=""
while [[ $reponse != [oOyYnNaAcC] ]]
do
titre="récupération des UUID et LABEL des partitions des disques"
texte="
			Récupération des infos dans les fichiers $fich_recup des partitions
			ce programme travaille avec sudo pour
			récupérer les dev (blkid)
			effectuer des montages/démontages
			(mot de passe d'administration requis)

	répondez par	
			(oOyY) pour lancer la commande sudo blkid ( remise à jour du fichier) 
			(aA)   pour arrêter ce programme

					O pour récupérer les devices via \"sudo blkid\"
					A Arrêter
"
reponse=`zenity --entry --title "$titre" --text "$texte" --width "800"`
case $reponse in
	[oOyY]	) echo "sudo blkid" ; sudo blkid > $res_blkid								;;
	[aA]	) echo "arrêt du programme" 				; exit 1	;;
	*		) echo "$reponse utilisez seulement oOyYaA S.V.P."				;;
esac
done



rm "$fich_fstab_conc"
touch "$fich_fstab_conc"
#echo "# $num : couples uuid-boot - uuid-systeme des menuentry en boot séparé" > $fich_fstab_conc

# récupération des dev label et UUID 
unset uuid
unset label
unset bdev		# V31 pour boot séparé
unset bmont 	# pour le point de montage à cause du boot séparé
unset btype 	# le type de la partition


maxuuid=-1
while read ligne 		# lecture et traitement du fichier généré par sudo blkid
do
# c'est le même script que dans modif-grub
# certaine lignes sont inutiles mais je les ai laissées
	[[ -z $ligne ]] && echo "ligne vide je passe" && continue		# correction ligne vide
	
	((maxuuid++))
	# d'abord le dev
    DEV=$(awk -F":" '{print $1}' <<< "$ligne") # donne aussitôt /dev/sda1
    # pour les autres , à cause d'espaces possibles (dans le label)
    # il faut mettre un espace devant chaque
    # à cause de PARTLABEL par exemple 
    if grep " LABEL" <<< $ligne
        then
            # -r : utilisation Ere de sed
            #  ([^"]+) mémorise suite non nulle de caractères différents de "
            # \b devant la chaine pour indique une chaine vide ? (moi j'aurais mis espace) 
            LABEL=$(echo ${ligne}|sed -r 's/.*\bLABEL="([^"]+)".*/\1/')
        else
            LABEL=""
            echo "pas de LABEL"
        fi
  
    
    if grep " UUID" <<< $ligne
        then
            UUID=$(echo ${ligne}|sed -r 's/.*\bUUID="([^"]+)".*/\1/')
        else
            UUID=""
            echo "pas d'UUID"
        fi
        
    if grep " TYPE" <<< $ligne
        then        
            TYPE=$(echo ${ligne}|sed -r 's/.*\bTYPE="([^"]+)".*/\1/')
        else
            TYPE=""
            echo "pas de type"
        fi
    
    if grep " PARTUUID" <<<$ligne
        then
            PARTUUID=$(echo ${ligne}|sed -r 's/.*\bPARTUUID="([^"]+)".*/\1/')
        else
            PARTUUID=""
            echo "pas de partuuid"
        fi

	[[ -z `grep "^\/dev" <<< $DEV` ]] && echo \
		&& echo "il manque /dev dans la ligne $ligne du fichier de référence UUID-LABEL" \
		&& exit 1

	
	# init variables d indice maxuuid
	   dev[maxuuid]=$DEV		# le dev de la ligne blkid
	  label[maxuuid]="$LABEL"			# le label de la ligne blkid
	   uuid[maxuuid]="$UUID"			# l uuid de la ligne blkid
	  btype[maxuuid]="$TYPE"			# le type de la ligne blkid
	mnt_dev[maxuuid]="1"		# modifié par mount : 0 si le dev est monté
	  p_dev[maxuuid]=""			# modifié par mount : point de montage



done <$res_blkid

# artifice pour créer un uuid  en double
# uuid[11]="78684472684430E4"
# artifice pour créer un label en double
# label[8]="U16.04-b10-64b"

# mise à zéro du fichier
rm "$fich_double_label_uuid"
touch "$fich_double_label_uuid"


#vérifier l'unicité des LABEL dans le tableau label
for i in ${!label[@]}
do
	for j in ${!label[@]}
	do
		[[ $i -ne $j ]] && [[ ${label[$i]} = ${label[$j]} ]] && [[ -n ${label[$i]} ]] && echo "${dev[$i]} ${label[$i]} ${uuid[$i]}" >> "$fich_double_label_uuid"
	done
done


#vérifier l'unicité des UUID ( cas de disques ajoutés ) dans le tableau uuid

for i in ${!uuid[@]}
do
	#echo ${uuid[$i]}
	for j in ${!uuid[@]}
	do
		#echo ${uuid[$i]} ${uuid[$j]}
		[[ $i -ne $j ]] && [[ ${uuid[$i]} = ${uuid[$j]} ]]  && [[ -n ${uuid[$i]} ]] && echo "${dev[$i]} ${label[$i]} ${uuid[$i]}" >> "$fich_double_label_uuid"
	done
done


# si le fichier n'est pas vide , avertir et sortir si demande 
[[ -s "$fich_double_label_uuid" ]] && continuer "ATTENTION LABEL et/ou UUID en DOUBLE"


#récupération des partitions déjà montées

mount | grep '^\/dev' > tmp.txt
#     1         2   3        4    5    6
#    /dev/sda11 on /media/SH type ext4 (rw,relatime,data=ordered)

	# remarque :
	# awk -F" " '{printf ("%s ",$1)}' tmp.txt 
	# donne
	# tous les dev séparés par une espace grace à "%s "

	# awk -F" " '{printf ("%s ",$3)}' tmp.txt 
	# donne
	# tous les points de montage séparés par une espace grace à "%s "

mdev=(`awk -F" " '{printf ("%s ",$1)}' tmp.txt`)	# les dev montés dans un tableau
mont=(`awk -F" " '{printf ("%s ",$3)}' tmp.txt`)	# les points de montage dans un tableau

rm "tmp.txt"


# positionnement montée ou non de chaque dev
for i in ${!dev[@]}						# pour tous les indices des dev
do
	for j in ${!mdev[@]}				# pour tous les indices des partitions montées
		do
			if [[ "${dev[$i]}" = "${mdev[$j]}" ]]
				then
					mnt_dev[i]="0"			# 0 indique que le dev est montée
					p_dev[i]=${mont[$j]}    # le point de montage du dev
					break
				fi
		done
done


# sortie des uuid label pour info
		[[ -e "tmp_u_l.txt" ]] && rm "tmp_u_l.txt"
echo
		p=0
		while [[ $p -le $maxuuid ]]
		do
			    aff_dev="${dev[$p]}"	 	# jamais vide
			aff_mnt_dev="${mnt_dev[$p]}" 	# vaut 0 (monté)  ou 1 (non monté)
			  aff_p_dev="${p_dev[$p]}"		# (affichage en fonction du précédent)
			# pour les corrections d'affichage 
			 aff_uuid="${uuid[$p]}"		&& [[ -z "$aff_uuid"	 ]]	&& aff_uuid="_"
			aff_label="${label[$p]}"	&& [[ -z "$aff_label"	 ]]	&& aff_label="_"
			aff_btype="${btype[$p]}"	&& [[ -z "$aff_btype"	 ]]	&& aff_btype="_"

			case $aff_mnt_dev in
			0)
				printf "%02s %-10s %-36s LABEL %-20s sur %-20s TYPE : %-10s\n" "$p" "$aff_dev" "$aff_uuid" "$aff_label" "$aff_p_dev" "$aff_btype"  | tee -a tmp_u_l.txt ;;
			1)
				printf "%02s %-10s %-36s LABEL %-20s                          TYPE : %-10s\n" "$p" "$aff_dev" "$aff_uuid" "$aff_label"  "$aff_btype"			| tee -a tmp_u_l.txt ;;
		
	esac	

			((p++))											
		done

reponse=""
titre="concordances     dev<=>LABEL<=>UUID<=>point de montage (de blkid)     Visualiser   puis Valider pour continuer"
zenity --text-info --title "$titre" --filename "tmp_u_l.txt" --height "640" --width "1280" --font "Courier New Bold 10"
code=$?
        [[ -e "tmp_u_l.txt" ]] && rm "tmp_u_l.txt" # supprime ce fichier devenu inutile
if [[ $code -eq 0 ]]
then
	echo "OK je continue"
else
	echo ; echo "Annulation demandée" ; echo ; exit 63
fi


##################################################
# pour cette partie il est absolument nécessaire d'avoir une liste des dev corrects
# d'où le sudo blkid effectué plus haut !
##################################################

echo "récupération des fstab de toutes les partitions"			 > $fich_fstab_long
echo 															>> $fich_fstab_long

############################################################
echo "pour les partitions déjà montées :" 						>> $fich_fstab_long
echo ${!dev[@]}

for i in ${!dev[@]} # pour tous les indices du tableau dev

	do
		echo $i ${dev[$i]} ${mnt_dev[$i]}
		[[ ${mnt_dev[$i]} = "1" ]]	&& continue		# non monté suivant !
		[[ ${btype[$i]} = "ntfs" ]]	&& continue 	# ntfs      suivant !
		[[ ${btype[$i]} = "swap" ]]	&& continue 	# swap      suivant !
		# on pourrait en ajouter d'autres

		echo  													>> $fich_fstab_long
		echo ${dev[$i]} "montée sur" ${p_dev[$i]} 				>> $fich_fstab_long

		#pour chaque dev monté on récupére les infos de fstab
		fich=${p_dev[$i]}$fich_recup 
		fich=`sed 's/\/\//\//g' <<< $fich` # supprime les doubles // (à cause de  //etc/fstab)

		echo $fich	#soit /etc/fstab soit /xxx/xxx/etc/fstab
		
		if [[ -e $fich ]]
			then
				echo  											>> $fich_fstab_long
				echo "$fich de ${dev[$i]}"  					>> $fich_fstab_long
				# on ne garde que les lignes non commentées et non vide

				dev_part=""
				dev_boot=""
				while read l_fstab
					do
						tmp=` grep '^[[:blank:]]*\#' <<< $l_fstab`
						#si tmp n est pas vide , elle commence par #
						if [[ -z $tmp ]] && [[ -n $l_fstab ]]
							then 
								echo $l_fstab >> $fich_fstab_long
								trans_ligne_fstab "$l_fstab"
							fi
					done < $fich
		ecrit_ligne_court "${dev[$i]}" "$dev_part" "$dev_boot"
			else
				echo 									>> $fich_fstab_long
				echo "pour ${dev[$i]} (${label[$i]}) /etc/fstab est inexistant"	>> $fich_fstab_long
			fi
	done

echo >> $fich_fstab_long

##############################################################
echo "pour les partitions non montées :" >> $fich_fstab_long


if [[ -e "/mnt" ]]
then
	echo "réperoire /mnt présent"
else
	echo "le répertoire /mnt n'existe pas !!!"
	exit 1
fi


rep_mnt_tmp="/mnt/jpb-$num"
echo "création du répertoire $rep_mnt_tmp pour monter les partitions"

sudo mkdir $rep_mnt_tmp

for i in ${!dev[@]} # pour tous les indices du tableau dev
do
	echo $i ${dev[$i]}

	[[ ${mnt_dev[$i]} = "0" ]]	&& continue		# montée    suivant !
	[[ ${btype[$i]} = "ntfs" ]]	&& continue 	# ntfs      suivant !
	[[ ${btype[$i]} = "swap" ]]	&& continue 	# swap      suivant !

	echo
	echo "traitement de $i ${dev[$i]} (${btype[$i]})"
	echo "montage de       ${dev[$i]} sur $rep_mnt_tmp"
	sudo mount ${dev[$i]} $rep_mnt_tmp
	code=$?
	
	echo "code de retour montage de ${dev[$i]} sur $rep_mnt_tmp : $code"
	if [[ $code = 0 ]]	# si le montage est réussi
		#################### montage réussi ####################
		then
			fich=$rep_mnt_tmp/etc/fstab
			if [[ -e $fich ]]
				then
					echo 							>> $fich_fstab_long
					echo ${dev[$i]} montée sur $rep_mnt_tmp	>> $fich_fstab_long
					dev_part=""
					dev_boot=""					
					while read l_fstab
							do
								tmp=` grep '^[[:blank:]]*\#' <<< $l_fstab`
								# si ne commence pas par # , tmp est vide 
								# et si la ligne n'est pas vide on l'écrit
							if [[ -z $tmp ]] && [[ -n $l_fstab ]]
								then 
									echo $l_fstab 					>> $fich_fstab_long
									trans_ligne_fstab "$l_fstab"
								fi
							done < $fich
		ecrit_ligne_court "${dev[$i]}" "$dev_part" "$dev_boot"
				else
		echo															>> $fich_fstab_long
		echo "pour ${dev[$i]} (${label[$i]}) /etc/fstab est inexistant" >> $fich_fstab_long
				fi
			# puis on le démonte avec boucle sinon le démontage ne se fait pas toujours
			boucle=0
			code=1
			while [[ $code -ne 0 ]]
			do
				sudo umount "$rep_mnt_tmp"
				code=$?
				echo "boucle $boucle  : ${dev[$i]} code de retour de umount $code"
				if [[ $code = 0 ]]
					then
						echo 
						echo "boucle $boucle : ${dev[$i]} démontage effectué (code retour $code)"
						ls -ails $rep_mnt_tmp
					else
						echo
						echo "boucle $boucle : ${dev[$i]} non démonté (code retour $code)"
						sleep 1 # attente en cas de non démontage
						((boucle++))
						if [[ $boucle -ge 10 ]]
							then
								echo "problème de démontage de ${dev[$i]}"
								exit 1
							fi	
					fi
			done # boucle while
		############################ échec de montage ###################
		else
			echo																	>> $fich_fstab_long
			echo "impossible de monter ${dev[$i]}  code echec de montage :$code"	>> $fich_fstab_long
		fi
done # boucle for i dev

echo ; echo
echo "fin de récupération des données de /etc/fstab des partitions présentes sur la machine"
echo ; echo

# sauvegarde de UBoot_UPart pour une utilisation personnelle
cp "$fich_fstab_conc" "$fich_fstab_conc_num"

echo "suppression du répertoire $rep_mnt_tmp en cours"
sudo rmdir $rep_mnt_tmp
code=$?

if [[ $code -ne 0 ]]
	then 
	#rmdir: échec de suppression de '/mnt/jpb-2017:03:11-12:02:43': Périphérique ou ressource occupé
		echo
		ls -ails /mnt/jpb*
		echo "vérifier le contenu du répertoire /mnt/jpb"
		echo "faire le ménage dans ce répertoire"
		exit 1
	fi

echo "suppression réussie"
echo "fin normale du programme $0"

PC          : B760M DS3H DDR4,  12th Gen Intel(R) Core(TM) i3-12100, RAM DDR4 8GiB -2400 Ubuntu 20.04, 22.04, 24.04 (en test )
Portable1 : ThinkPad P50 I7-6820HQ, 16G0 Ram Ubuntu 22.04 Ubuntu 24.04 , W10-PRO( en voyage )
Portable2 : T5750  @ 2.00GHz RAM 1GiB DDR2 667 Mhz Ubuntu 20.04 ( batterie HS )
stourm a ran war bep tachenn (Angela Duval) ( Je combats sur tous les fronts )

Hors ligne