Coloration en shell/bash
Résolu/FerméTheo_0055 Messages postés 275 Date d'inscription mardi 21 juillet 2020 Statut Membre Dernière intervention 19 janvier 2023 - 20 déc. 2022 à 17:53
- Coloration en shell/bash
- Classic shell windows 11 - Télécharger - Personnalisation
- Bingo bash free - Télécharger - Divers Jeux
- Shell pause ✓ - Forum Shell
- Faites afficher avec un fond coloré les cellules qui contiennent une valeur comprise entre 250 et 350. quel nombre est dessiné en surbrillance ? - Forum VB / VBA
- Bash addition ✓ - Forum Shell
19 réponses
8 déc. 2022 à 00:38
Bonjour,
Quand bien même comprendrais-je quoi que ce soit au bash (et je n'y comprends rien) que le but est de comprendre l'énoncé pour pouvoir faire l'exercice, pas de le faire à ta place.
On ne peut pas dire que l'on ne comprend rien au commutateur max depth sans avoir cherché, et la réponse (illustrée) s'obtient en 2 clics; c'est un équivalent beaucoup plus puissant de la commande DIR sous Windows, qui elle ne permet pas de spécifier la profondeur de l'affichage: n précise qu'on cherchera les répertoires à n niveaux sous la racine, on te facilite donc la vie en ne choisissant que le premier où il n'y a pas de risque que tel dossier 1 contienne des dossiers 2 et un autre pas:
https://ss64.com/bash/du.html
Nous obtenons comme précisé dans l'énoncé et sur l'illustration la taille occupée par chaque répertoire et la taille totale; on peut supposer qu'il existe plus de 24 dossiers, mais l'hypothèse de coloration successive de chaque répertoire en fonction de sa taille absolue est absurde puisque je n'ai que 24 couleurs à ma disposition (plus une si un seul répertoire occupait tout l'espace).
Elle l'est de plus parce que, faute d'avoir utilisé le commutateur -all, la commande n'a ramené que les répertoires, pas les fichiers isolés, et que le total peut être plus grand que la somme de chaque répertoire: je vais donc raisonner en pourcentage et calculer le pourcentage que chaque dossier occupe par rapport à l'espace global, et qui lui peut faire "doublon" dans la même tranche même si j'ai plus de 24 répertoires.
Nous avons décidé de 25 codes couleur de 0 à 24 et dont les niveaux de gris sont respectivement de 231 pour 0 puis décroissant de 255 à 232 pour 1 à 24.
Nous remarquons que dans la première règle la valeur (c+1)/24 est exclue de l'intervalle, la valeur maximale que c puisse prendre sans que t atteigne 1 est donc 23 (sinon 2ème règle): il va donc suffire pour chaque valeur de t d'itérer le calcul des règles de c, de comparer pour chaque c le résultat à t pour retourner la valeur de c encadrant t, cette valeur de c elle-même appelant l'affichage du code niveaux de gris 231 pour c=0, décroissant de 255 à 233 pour c croissant de 1 à 23, 232 pour c=24.
8 déc. 2022 à 13:46
Merci j'ai un peu mieux compris .Je vais essayer de le faire
8 déc. 2022 à 18:40
Bonjour,
J'avoue que l'énoncé n'est pas des plus limpides.
La commande du permet de lister les fichiers contenu dans une arborescence donné. Comme on parle d'arbre, on peut définir une notion de profondeur (0, à partir de sa racine). Donc par exemple, si tu lances la commande :
du .
tu listes tous les fichiers contenu dans le dossier courant ".". Tu peux choisir de partir d'un autre dossier (par exemple /home). Celui-ci désigne la racine de l'arbre considéré.
- Les fichiers/dossiers directement contenus dans le dossier servant de racine ont pour profondeur 1,
- Les fichiers/dossiers contenus dans un dossier de ont une profondeur égale à 1,
- Les fichiers/dossiers contenus dans un sous-dossier de "." une profondeur égale à 2 et ainsi de suite.
- etc.
Ainsi, si tu lances :
du --max-depth=2 /home
... tu affiches les fichiers/dossier contenus dans /home (profondeur 1), les fichiers et sous-dossiers que contiennent ces dossiers (profondeur 2), mais tu ne vas pas plus profondément dans l'arborescence (max-depth=2).
Tu peux essayer de faire varier les paramètres de cette commande pour te familiariser avec ces notions.
La commande du (disk usage) a pour but de voir combien de consomme chaque fichier et dossier ainsi listés. Elle est traditionnellement utilisée quand on manque d'espace disque (ou qu'on le trouve anormalement rempli). Dans un tel contexte, on comprend assez rapidement la pertinence de cette option (surtout si on part de / !).
Ensuite, l'idée est d'afficher chaque ligne retournée par du en fonction de la proportion d'espace consommé par un fichier. Comme le dit brucine #1, c'est sans doute une bonne idée d'utiliser l'option --all pour avoir un résultat qui a plus de sens même si l'énoncé n'en parle pas. Le taux d'occupation est une valeur comprise t dans {0, ..., 100}, que tu veux convenir dans une valeur dans {232, ..., 255}.
On passe donc d'un espace qui contient 101 valeurs à un espace qui en contient 24, il faut donc faire une règle de trois et décaler les valeurs obtenues pour retomber dans {232, ..., 255}. La règle de ton énoncé précise comment faire ce calcul. Là où l'énoncé est un peu vache, c'est que c n'est pas explicitement exprimé en fonction de t. Il faut donc que tu réfléchisses un peu à cette partie, typiquement en tenant compte des indices donnés par brucine.
Une fois que ce sera fait, ton algorithme consiste à faire ceci :
- Lancer la commande du (avec un profondeur de 0) pour obtenir la taille totale
- Pour chaque ligne retournée par du avec la profondeur désirée (par exemple 2)
- Extraire l'espace consommé et le normaliser par rapport à la taille totale pour obtenir la valeur t correspondante
- En déduire la valeur c correspondante
- Ecrire la ligne courante en utilisant la couleur c déduite.
Bonne chance
Modifié le 8 déc. 2022 à 19:31
Bonsoir j'ai esayé d'écrire ceci mais j'arrive toujours pas a trouver ou est le soucis dans mon code
touch fichier_temporaire1 touch fichier_temporaire2 du -all --max-depth=1 | cut -f 2 > fichier_temporaire1 #supprier la derniere ligne du fichier sed -i '$d' fichier_temporaire1 du -all --max-depth=1 | cut -f 1 > fichier_temporaire2 otot=$(tail -n 1 fichier_temporaire2) for c in seq 0 24 do while read octet do t=octet/otot if [$t -ge c/24] && [$t -lt \(c+1\)/24] then if [c -eq 0] then niveau_gris=231 else niveau_gris=255+c-1 fi else niveau_gris=232 fi while read repertoire do echo -e "\e[38;5;${niveau_gris}m$repertoire" done < "fichier_temporaire1" done < "fichier_temporaire2" done
Ca me dit que ligne 17: [octet/otot: Aucun fichier ou dossier de ce type
La ligne du if c'est bizarre
Pour expliquer mon code
J'ai mis dans fichier temp 1 le nom des repertoire ensuite j'enleve la derniere ligne car pas besoin c'est juste un point
Je met dans fichier 2 les octets du champ 1
Je fais une itération sur c,je calcule pour chaque octet (associé a un reperoire) son taux d'occupation en proportion
Ensuite pour les trucs de niveau de gris on sait que
Pour c=0 on a 231
Pour c=1 on a 255
Pour c=2 on 254
etc
Pour c=23 on a 233
Pour c=24 on a 232
Mon raisonnement est il faux?
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre questionModifié le 9 déc. 2022 à 15:04
Bonjour,
Pourquoi crées-tu un fichier temporaire ? Tu peux injecter le résultat d'une commande dans une variable (ou même dans une autre commande shell). Voir l'opérateur `...` en shell qui s'écrit aussi $( ... ) en bash.
Ensuite je pense que ta structure de programme n'est pas idéale, tu devrais plutôt repartir de celle que je t'ai suggérée dans #3 qui me paraît plus naturelle.
Ligne 17, si tu veux récupérer le contenu de la variable c, il faut écrire $c. En shell tu peux utiliser la commande expr pour évaluer un calcul, en bash, tu peux utiliser l'opérateur $(( ... )) comme l'explique cette discussion.
x=100 y=$((x / 3)) echo $y
Bonne chance
9 déc. 2022 à 17:45
En fait j'ai utilisé des fichiers temporaires car si je fait:
texte=$(du --max-depth=1)
ca m'affiche
du coup si j'écris:
taille=$(echo $ligne | cut -f1) nom=$(echo $ligne | cut -f2)
taille vaut 12 normal mais nom il vaut aussi 12 je pense c'est a cause du fait que la ligne 1 n'est pas bien aligné par rapport aux autres
Bon en dehors de ça j'ai ecris l'algo a peu pres que vous avez dit mais je peux pas tester encore s'il marche a cause pour l'instant d'une mauvaise récupération des valeurs.Pour taille ok mais nom ca marche pas,c'est pour cela de base j'ai créé un fichier temporaire pour resoudre ce soucis
taille_total=$(du --max-depth=0) texte=$(du --max-depth=1) for ligne in $texte do taille=$(echo $ligne | cut -f1) nom=$(echo $ligne | cut -f2) t=$(echo "scale=2; $taille/$taille_total" | bc) c=0 while [ $c -le 24 ] do a=$(echo "$c/24" | bc) b=$(echo "($c+1)/24" | bc) if [[ ($t -ge a) && \( $t -lt b) ]] then echo -e "\e[38;5;$(echo "....." | bc)m$nom" else .... fi c=$(echo "$c+1" | bc) done done
Dans les pointillés je sais pas encore quoi mettre la relation entre c et t j'arrive toujours pas a trouver le lien entre les deux
9 déc. 2022 à 18:11
Bonjour,
C'est un bon début.
Voici un bout de code à partir duquel tu peux démarrer. Il ne reste essentiellement plus qu'à calculer la bonne couleur et adapter l'affichage en conséquence.
#!/bin/bash total_size=$(du --max-depth=0 --all | cut -d" " -f1) du --max-depth=1 | while read -r line do echo $line size=$(echo "$line" | cut -d" " -f1) name=$(echo "$line" | cut -d" " -f2) normalized_size=$((100 * size / total_size)) echo "$normalized_size% $name" done
Bonne chance
9 déc. 2022 à 19:15
total_size=$(du --max-depth=0 --all | cut -f1) du --max-depth=1 | while read -r line do echo $line size=$(echo "$line" | cut -f1) name=$(echo "$line" | cut -f2) normalized_size=$((100 * size / total_size)) echo "$normalized_size% $name" #calculer la couleur color=0 while [ $color -lt 24 ] do if [ $normalized_size -ge $((color * 100 / 24)) ] && [ $normalized_size -lt $(((color + 1) * 100 / 24)) ] then if [ $color -eq 0 ] then color=231 else color=$((255 - color + 1)) fi else if [ $normalized_size -eq 100 ] then color=24 fi color=$((color + 1)) done echo -e "\e[38;5;${color}m$line" done
j'ai esayé d'écrire ceci sauf que on me dit que ligne ...: erreur de syntaxe près du symbole inattendu « done »
Le 1er done,normalement j'ai bien fermé non? les 2 while
Modifié le 12 déc. 2022 à 20:08
Finalement, pour que l'erreur disparaisse, j'ai changé else if et then par else mais je n'arrive toujours pas à comprendre pourquoi ça posait problème
12 déc. 2022 à 20:09
else if n'existe pas en shell, c'est elif.
Modifié le 12 déc. 2022 à 20:11
Autre problème, mon répertoire ressemble à ça
Le fichier .sh que je veux exécuter se trouve dans le répertoire 4. Et ce répertoire contient seulement 2 fichiers.
Si je me place dans rep4 (sans cela je peux pas exécuter mon fichier contenant le script) du max depth=1 affiche que la taille total
Je veux que si je me place dans rep4 ,qu'il fasse un du max depth=1 au niveau du répertoire contenant rep1,rep2,...(à savoir MINI_PROJ. Mais j'ai pas trouvé d'option de la commande du qui remonte au repoertoire parent contenant les dossiers
Modifié le 12 déc. 2022 à 20:21
Bonjour,
Comme je l'ai expliqué dans le message #3, la commande du prend en paramètre le répertoire qui définit la racine de l'arborescence que la commande parcours. Ainsi, pour exécuter du depuis le dossier parent il suffit d'écrire :
du ..
Concernant l'exécution du script, rien n'oblige à être dans rep4. Tu peux parfaitement te placer dans le dossier MINI_PROJ et l'invoquer n'importe laquelle de ces commandes (en supposant que MINI_PROJ est dans /home/toto)
rep4/mon_script.sh ./rep4/mon_script.sh /home/toto/MINI_PROJ/rep4/mon_script.sh ~toto/MINI_PROJ/rep4/mon_script.sh ~/MINI_PROJ/rep4/mon_script.sh # Si on est loggué en toto
- Quand tu lances un exécutable, soit celui-ci est positionné dans l'un des dossiers référencés dans la variable d'environnement PATH, soit il faut indiquer son chemin, sans quoi le shell ne va pas trouver pour toi le chemin de cet exécutable.
- Pour des raisons de sécurité, le dossier courant "." n'est normalement jamais défini dans PATH. Donc si ton script est dans /home/toto/MINI_PROJ/rep4, comme ce dossier n'est pas référencé dans ton PATH, même si tu es positionné dedans, le shell ne comprendrera pas que tu parles de ce script. C'est ce qui t'oblige en pratique à écrire ./mon_script.sh.
- Comme le montrent les commandes précédentes, du moment que le chemin de l'exécutable (en l'occurrence ton script shell) est explicité, alors il n'y a plus de problème...
- Pour voir le contenu de ton PATH, lance :
echo $PATH
Bonne chance
12 déc. 2022 à 14:00
Bonjour,
Tu devrais chercher une formule (en faisant un peu de maths) qui permet d'obtenir la couleur à partir de la valeur normalisée. Cela simplifierait grandement le code et le rendrait plus efficace.
Bonne chance
Modifié le 12 déc. 2022 à 20:27
Oui, c'est ça que j'ai fait : j'ai dit couleur=255_c+1 pour c allant de 1 23
Modifié le 12 déc. 2022 à 20:28
- Non, tu devrais chercher une formule qui calcule la nuance de gris en fonction de la taille normalisée.
- Appelons cette fonction f(s) où s est la taille normalisée dans {0, ... 100}, alors f devrait retourner une valeur c dans {232, ... 255} (ce devrait même être une fonction strictement monotone). Strictement croissante ou strictement décroissante en fonction de la convention de couleur que tu choisis (soit d'autant plus foncé que le fichier est gros, soit d'autant plus clair qu'il est gros)
- Pour cela il faut appliquer un facteur d'échelle à s (puisque la plage de 101 éléments) de sorte à prendre dans {0 ... 23} (donc une plage de 24 éléments) puis ajouter 232 à cette valeur pour obtenir une valeur dans {232, ... 255}.
- Peux-tu écrire une telle fonction ? Il n'y a pas de boucles ou je ne sais quoi, c'est une fonction qui utilise les opérations /, +, et partie_entière.
Bonne chance
Modifié le 12 déc. 2022 à 20:28
Et est-ce que vous avez des réponses à mes autres questions ?
12 déc. 2022 à 20:26
Oui, voir les commentaires que j'ai ajouté pour chacune d'elles.
13 déc. 2022 à 18:27
merci je vais essayer d'y reflechir ce soir
Modifié le 15 déc. 2022 à 18:38
Concernant la conversion taille vers couleur, voici comment tu peux la calculer (selon dans quel sens se fait la nuance de gris), à convertir en syntaxe bash :
c = s * 23 / 100 + 232 # "c" est d'autant plus grand que "s" est grand c = 255 - s * 23 / 100 # "c" est d'autant plus grand que "s" est petit
Dans les deux cas, c est à valeur dans dans {232 ... 255} si s est à valeur dans {0, ..., 100}.
Tu vois donc qu'il n'y a pas besoin de se lancer dans une boucle compliquée pour déterminer c en fonction de s...
Modifié le 15 déc. 2022 à 18:39
Bonjour
Merci, car je galérais un peu.
Je vois que mon idée n'était pas fausse, j'ai fait comme vous le c = s * 24 etc sauf que lorsque j'ai pris ma calculette par exemple 100*24 / 332 ca me donne 7,... du coup pour moi je m'étais trompé car normalement la valeur doit être entre 232 et 255.
15 déc. 2022 à 18:51
Ah c'est sûr que si tu divises par 332 (qui sort je ne sais pas trop d'où)...
Dans le calcul que je fais, l'idée est de voir la fonction de conversion "taille normalisée vers couleur" comme une fonction affine y = f(x) = a.x + b où y est la couleur (c) et x est la taille normalisée (s).
- Pour trouver a, l'idée est d'appliquer à la valeur entre 0 et 100 un facteur d'échelle (c'est la multiplication par 23 / 100). Le signe que l'on donne à "a" indique si c doit augmenter ou diminuer avec s.
- Si on choisit a = 23 / 100 alors la valeur de c augmente avec s augmente.
- Si on choisit a = -23 / 100 alors la valeur de c diminue quand s augmente.
- Le signe détermine donc dans quel sens la nuance de gris évolue avec s (de plus en plus foncé ou de plus en plus clair)
- La valeur de "b" correspond à la couleur obtenue quand s = 0. En effet f(0) = b. C'est donc la nuance de gris choisie que l'on souhaite associer à un fichier de taille nulle.
- On peut vérifier que quelle que soit la fonction de conversion choisie parmi les deux que je propose, {f(0), f(100)} = {232, 255}
15 déc. 2022 à 19:03
Ah d'accord je viens de tout comprendre merci.J'essayerais chez moi apres et je vous dirai
17 déc. 2022 à 15:25
Merci beaucoup je pense que c'est bon
18 déc. 2022 à 17:45
Eh bien félicitations, n'hésite pas à partager le résultat final ;-)
20 déc. 2022 à 12:30
La solution
total_size=$(du --max-depth=0 --all | cut -f1) du --max-depth=1 | while read ligne do size=$(echo "$ligne" | cut -f1) name=$(echo "$ligne" | cut -f2) normalized_size=$((100 * size / total_size)) niveau_gris=$((255-normalized_size*23/100)) echo -e "\e[48;5;${niveau_gris}m$size $name\e[0m" done
en fait la solution ne marche pas a 100% car dans certain cas il marche pas
Par exemple si j'obtiens :
size=16,01541...% qui est arrondit a 16%
niveau_gris=255-16*23/100=
16*23/100=3,68 maiss vu que ca prend que la partie entiere renvoie 3
Et donc on aura 255-3=252 or le bon résultat est 253 (car si c=3 je dois obtenir 253)
20 déc. 2022 à 16:14
Merci pour ton retour, je n'ai pas trop compris pourquoi le bon résultat devait être 253 et pas 252 puisque ta règle de 3 permet bien d'avoir tout le spectre de 0 à 255 inclus. Mais bon, je pense que c'est imperceptible à l'œil nu et à mon avis ton enseignant considérera que l'exercice est résolu dans l'esprit qu'il attendait.
Modifié le 20 déc. 2022 à 16:49
Petit rappel:
Pour c=0 on a 231
Pour c=1 on a 255
Pour c=2 on 254
Pour c=3 on a 253
..................................
Pour c=23 on a 233
Pour c=24 on a 232
en utilisant la règle suivante :
- dans la couleur c si t∈[c/24;(c+1)/24[
- dans la couleur 24 si t=1
en fait on m'a donné :
si l'occupation a savoir normalized_size appartient a l'intervalle[c/24;(c+1)/24[ on pourra en déduire le bon c
Par exemple 0,1601541 il appartient a l'intervalle [3/24;4/24[=[0,125;0,16666666...[
donc la bonne valeur de c est 3 et si je fais 255-3=252 et non 253
Mais bon pas grave,au moins dans mon exo le site me dit j'ai que 62% de réusssite
20 déc. 2022 à 17:05
J'ai normalisé par 23, peut être que c'est par 24. Tu as testé ?
20 déc. 2022 à 17:53
Oui j'ai testé ça change pas mon résultata(62%)
Bref c'est pas grave,moi aussi je trouve bizarre que j'ai pas 100% apres je sais pas quel test il y a derrière