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.

#26 Le 15/02/2010, à 01:12

Totor

Re : [JEU] challenge bash #2

Bonjour,

Je vois que les choses ont évoluées depuis hier.

Si je résume, il y a 4 écoles :
- while read
- copie avec process en background
- strace
- compteur de ligne

Mes remarques :
1ère méthode (je ne parle pas de la 1ère version du script d'AnsuzPeorth) : à moins que cela ait changé avec vos versions de bash, l'utilisation du read n'est pas fiable chez moi.
Je vous laisse comprendre pourquoi :

echo " lettre a  " > unfichier.test
read a < unfichier.test
echo "-${a}-"
rm unfichier.test

Aussi, suivant le fichier, il se peut qu'il y ait des problèmes de mémoire/swap : prenons l'exemple d'un fichier de 4Go sans retour chariot !! bon, c'est un cas extrême !!!

Sur les autres scripts, il y a un bug récurrent : que ce passe t'il si la copie est en erreur ? --> le script ne s'arrète pas.
en effet : tester la taille (d'une façon une d'une autre) comme étant la condition de fin est à mon sens une erreur. il faut donc procéder autrement...

c'est ce que j'ai utilisé dans ma version où l'objectif est d'identifier
- les modifications apportés au fichier destination afin de limiter la fréquence d'affichage
- la fermeture du fichier destination (= événement déclencheur de l'arrêt)
- la présence du job en background

Pour la méthode d'affichage, l'utilisation de printf est recommandée. Elle permet effectivement d'utiliser des séquences qui formattent pour nous la sortie souhaitée.

Concernant la méthode récursive de Ph3nix_, je ne sais pas ce qu'elle donnerait avec un énorme fichier ... il y aurait très probblement un problème de pile

Autre chose : je ne connaissais pas bar et je l'accèpte comme ultime solution car elle s'apparente à celle que je connais.

@AnsuzPeorth : il est dommage que tu n'utilises pas printf (mais tu t'en aies rendu compte)
- ton premier script est en erreur (je n'ai pas regardé pourquoi)

@toto2006 : ton script bug si il y a un dossier en 2nd paramètre. Et il est très consommateur de ressource

@Khyl : ton script n'affiche qu'1 %. Par ailleurs, l'utilisation de cut pour chacune des lignes est aussi très consommateur : imagine un fichier de 1G : à chaque boucle, cut le relit dès le début !!
@sputnick : merci d'avoir mis en avant l'utilisation de {A..B} et du formatage avec printf (note : ton script est buggé en cas de dossier en destination wink)

@Yannou90 : sur ton dernier script
- évite l'utilisation de $*, c'est beaucoup moins pratique que $@ et tu perds des informations.
- pour passer une chaine de caractère dans l'entrée standard d'une instruction, préfère l'utilisation de la syntaxe
instruction <<< chaine plutôt que echo chaine|instruction --> ex. TEMPS_PASS=$(bc <<< "scale=1; $TEMPS_PASS+0.2")
- pour la substitution de commande, préfère la syntaxe $(cmd) plutôt que `cmd` (ancienne forme). L'ancienne permet difficilement d'imbriquer des substitutions
- plutôt que d'utiliser tr ou sed pour changer ou supprimer un/plusieurs caractères d'une variable, tu peux utiliser la syntaxe ${variable/pattern/chaine}
pattern : pattern bash à substituer
chaine : chaine qui remplacera pattern
si tu veux remplacer plusieurs tous les patterns : ${variable//pattern/chaine}
si tu veux supprimer : ${variable/pattern} ou ${variable//pattern}


@Ph3nix_ : le gagnant (même si ils sont buggés en cas de dossier en destination) : les 2 scripts sont très courts (je n'ai pas pris en compte la gestion des paramètres)

mes versions

Dernière modification par Totor (Le 15/02/2010, à 01:17)


-- Lucid Lynx --

Hors ligne

#27 Le 15/02/2010, à 01:22

sputnick

Re : [JEU] challenge bash #2

Edit de mon post plus haut; Je rajoute

perl -e'print"100% [","="x100,">]\n";'

à la fin du while, comme ca meme si le fichier est petit, ca affiche un resultat cohérent.

Edit bis
@totor,

@sputnick : merci d'avoir mis en avant l'utilisation de {A..B} et du formatage avec printf (note : ton script est buggé en cas de dossier en destination

l'énoncé dit

Le challenge consiste à réaliser un script le plus petit possible (en terme de quantité d'instructions) ayant pour objectif de copier un fichier

donc mon ancien script n'est pas bugé, il répond au "cahier des charges" ^^

De toutes facons, j'ai implémenté l'idée ( bonne ) de mettre un cp en background et de calculer le % que toutes les N secondes. Mon script gere les erreurs et gere aussi les petits fichiers. Il gere uniquement les fichiers conformément à l'énoncé. ( il est pas difficile de le modifier si besoin pour dealer les répertoires ).

Dernière modification par sputnick (Le 15/02/2010, à 01:36)


On ne peut pas mettre d'array dans un string!
https://sputnick.fr/

Hors ligne

#28 Le 15/02/2010, à 01:30

Yannou90

Re : [JEU] challenge bash #2

Merci beaucoup pour ces précisions Totor

Cela fait un bout de temps que je tombe sur des bouts de codes "incompréhensible" pour moi,et tu vien de m'eblouir de simplicitée , il me faudrait un prof comme toi a la maison lol
Je rigoles mais plus serieusement cette idée de challenge est vraiment excellente !
Chacun peut apporter son point de vue/son idée directrice , et la concurence motive a mort !

Bravo a tous les participant (dans l'ordre d'apparition):
AnsuzPeorth
toto2006
Khyl
wido (pour bar ; je l'avais trouvé mais j'ai rien compris lol )
sputnick
Ph3nix_
Et les gourous nesthib et Totor

Hors ligne

#29 Le 15/02/2010, à 01:33

sputnick

Re : [JEU] challenge bash #2

Avec la coloration syntaxique c'est plus classe : http://pastie.org/824915


On ne peut pas mettre d'array dans un string!
https://sputnick.fr/

Hors ligne

#30 Le 15/02/2010, à 01:45

Yannou90

Re : [JEU] challenge bash #2

AAAAAAAAAAAAAAAAAAAAAA
je suis vert :

pv -s $(stat -c %s "$1") < "$1" >"$2"

Bouuuuuu!!!!!!!!!!!!! sad

Ah je savais que j'allais pleurer , sniffff
Le coup de pv trop fort,nickel pour mettre des progress de partout
Merci encore , sniff , sniff ......

Edit : euuu y a un soucis j'ai mis ta commande dans un script , executer sur un film ,j'ai vu la progress partir et quand les larmes me sont monter je suis venu sur le forum poster ce message , je poste retourne sur mon bureau et la le drame : mon script c'est transformer en un fichier equivalent a celui de la video , genre 580 mo ,je le renome pour le plaisir en test.avi et hop vlc me le lance , normal quoi ????

Y a un truc que j'ai loupé ??

Re-Edit : j'ai du faire le gros doigt avec le terminal pendant que je postait , c'est tout bon , desole roll

Dernière modification par Yannou90 (Le 15/02/2010, à 01:58)

Hors ligne

#31 Le 15/02/2010, à 01:49

sputnick

Re : [JEU] challenge bash #2

Ouais, mais non, pv on est pas mal à connaître, mais c'est pas le but AMHA ici !?


On ne peut pas mettre d'array dans un string!
https://sputnick.fr/

Hors ligne

#32 Le 15/02/2010, à 02:47

AnsuzPeorth

Re : [JEU] challenge bash #2

Totor a écrit :

Concernant la méthode récursive de Ph3nix_, je ne sais pas ce qu'elle donnerait avec un énorme fichier ... il y aurait très probblement un problème de pile

J'ai eu un problème avec un fichier de 700 Mo, la taille du fichier copié n'est pas égale à la taille du fichier source, obligé de tuer le sript il ne rendait plus la main, même ctrl+c inefficace (affichage 100 % mais tailles inégales)

Totor a écrit :

@AnsuzPeorth : il est dommage que tu n'utilises pas printf (mais tu t'en aies rendu compte)
- ton premier script est en erreur (je n'ai pas regardé pourquoi)

Il y a un problème de tabulation lors de la copie depuis le forum. C'est pour modifier la sortie de du, dans ma deuxième version, j'utilise stat (avant que tu en parles), je sais pas pourquoi je suis resté bloqué sur du ? des fois ...
J'ai regardé d'un peu plus prêt printf, que j'utilisais rarement, mais c'est vrai qu'il est bien pratique, bien qu'un peu complexe à comprendre !!!

l
    (elle) La conversion entière suivante correspond à un long int ou unsigned long int, ou la conversion n suivante correspond à un pointeur sur un long int, ou la conversion c suivante correspond à un argument wint_t, ou encore la conversion s suivante correspond à un pointeur sur un wchar_t.

Oauis.....!!!!

J'ai bien aimé l'astuce

    eval printf '%.0s=' {0..$percent}

Encore un challenge riche en enseignements !

Dernière modification par AnsuzPeorth (Le 15/02/2010, à 02:49)


Interface graphique pour bash, python ou autre: glade2script
Support Tchat: http://chat.jabberfr.org/muckl_int/inde … ade2script  (Hors ligne)

Hors ligne

#33 Le 15/02/2010, à 19:28

Ph3nix_

Re : [JEU] challenge bash #2

Totor a écrit :

@Ph3nix_ : le gagnant (même si ils sont buggés en cas de dossier en destination) : les 2 scripts sont très courts (je n'ai pas pris en compte la gestion des paramètres)

mes versions

tongue , je trouve ce challenge trés instructif

AnsuzPeorth a écrit :
Totor a écrit :

Concernant la méthode récursive de Ph3nix_, je ne sais pas ce qu'elle donnerait avec un énorme fichier ... il y aurait très probblement un problème de pile

J'ai eu un problème avec un fichier de 700 Mo, la taille du fichier copié n'est pas égale à la taille du fichier source, obligé de tuer le sript il ne rendait plus la main, même ctrl+c inefficace (affichage 100 % mais tailles inégales)

Bizarre, je copie le fichier avec cp, la taille a l'arrivée devrai être identique a la taille du début. Quoiqu'il en soit ce n'est pas un problème de pile, sinon tu aurais eu un message d'erreur (erreur de segmentation ou segfault)

Voici une version qui devrai résoudre ton problème:

#!/bin/bash
S_TOTAL=( $(du "$1") )
BAR="==================="

fct() {
	S=( $(du "$1") )
	printf "\rProg: $((p= S[0]*100 / S_TOTAL[0]))%s (${S[0]}kio/${S_TOTAL[0]}kio) [${BAR:0:(( p / 5))}>" "%"
	[ ${S[0]} -lt ${S_TOTAL[0]} ] && sleep 0.1 && fct "$1" || echo "]"; }

:> "$2"
(fct "$2" )&
cp "$1" "$2"

(j'ai remplacé -ne par -lt)
En ce qui concerne la surcharge de la pile, c'est peu probable:
J'ai testé un script qui s'appelait récursivement, la pile est surchargé environ autour de 1246x récursions. (12464 la première fois et 12468 la seconde)
Sachant que mon instruction doit s'exécuter toutes les 0.15s (instruction + sleep 0.1s)

Il faudrait donc que le copiage du fichier dure un peu plus de 30 minutes..

Dernière modification par Ph3nix_ (Le 15/02/2010, à 19:33)


Hiroshima 45 / Chernobyl 86 / Windows '95

Hors ligne

#34 Le 15/02/2010, à 20:37

AnsuzPeorth

Re : [JEU] challenge bash #2

Ph3nix_ a écrit :

Voici une version qui devrai résoudre ton problème

Tjrs pas ! Bizarre

Prog: 100% (725432kio/724720kio) [===================>]

Par contre si je remplace du par stat -c %s

Prog: 100% (742111232kio/742111232kio) [===================>]

Interface graphique pour bash, python ou autre: glade2script
Support Tchat: http://chat.jabberfr.org/muckl_int/inde … ade2script  (Hors ligne)

Hors ligne

#35 Le 15/02/2010, à 23:13

AnsuzPeorth

Re : [JEU] challenge bash #2

Pour mettre en application ce que j'ai tiré des exemples, j'ai un peu modifier le script (un mix avec celui de sputnick):
Malgrés un plus grand nombre d'instructions, le temps d'execution est identique (pour l'utilisation processeur, la différence est moindre).
La modification se porte essentiellement sur l'affichage, je l'ai 'bloqué'.

  61% [=============>        ] (38346kio/23636kio)
 100% [=====================>] (38346kio/38346kio)

(décommenter les 3 lignes pour n'avoir qu'une instruction printf et commenter les autres printf)

#!/bin/bash

S_TOTAL=$(($(stat -c %s "$1")/1024))
#BAR="==================="
#TROU="                   "
fct() {
    S=$(($(stat -c %s "$1")/1024))
    P=$((S * 100 / S_TOTAL))
    #printf "\r %3d%%  [${BAR:0:(( P / 5))}>${TROU:(( P / 5)):19}] (${S_TOTAL}kio/${S}kio)" $P
    printf "\r %3d%% [" $P
    eval printf "%.0s=" {0..$((P / 5))}
    printf ">%*c" $((21 - (P / 5)))
    printf "] (${S_TOTAL}kio/${S}kio)"
    [ ${S} -lt ${S_TOTAL} ] && sleep 0.1 && fct "$1"|| echo; }
:> "$2"
(fct "$2" )&
cp "$1" "$2"
sleep 0.1

exit

Dernière modification par AnsuzPeorth (Le 15/02/2010, à 23:27)


Interface graphique pour bash, python ou autre: glade2script
Support Tchat: http://chat.jabberfr.org/muckl_int/inde … ade2script  (Hors ligne)

Hors ligne

#36 Le 16/02/2010, à 00:31

Totor

Re : [JEU] challenge bash #2

@sputnick
désolé, je n'avais pas vu ton second script..tu l'as posté alors que je rédigeais mon post !
d'ailleurs, je constate que tu avais aussi opté pour le test de présence du process en background

j'ai une petite question : pourquoi positionnes-tu toujours tes redirections juste après l'instruction ?

Concernant les perfs :

$ stat -c dossier/debian-40r5-amd64-DVD-1.iso
4691185664
$ time forum.ubuntu-fr.org/challenge/copie.sh dossier/debian-40r5-amd64-DVD-1.iso ~
[============================================================================================================================================================================>]100%


real    1m57.147s
user    0m45.963s
sys    1m14.861s

$ rm debian-40r5-amd64-DVD-1.iso
$ time cp dossier/debian-40r5-amd64-DVD-1.iso .

real    1m56.341s
user    0m0.080s
sys    0m8.905s

Enfin, j'ai tenté une autre version en espérant gagner légèrement un perf car moins d'exécution d'inotifywait mais bien au contraire, j'ai perdu env. 30 sec   

#!/bin/bash
affiche()
{
  new_size=$(stat --printf=%s "${fic_dest}")
  pct="$(printf '%3.0f' $((new_size*100/size)))"
  [ "${pct}" != "${old_pct}" ] && {
	  old_pct=${pct}
  evolution="$(eval "printf '%.0s=' {0..$((pct*cols/100-2))}")>"
  texte="]${pct}%"
  echo -en "\r[${evolution}\r\033[$((${maxcols}-${#texte}))C${texte}"
}
}

# test du nombre de paramètres
[ $# -lt 2 ] && {
	echo "Usage : ${0##*/} source destination" >&2
	exit 1
}

# test existence du fichier à copier
[ -f "${fic_src:=$1}" ] || {
	echo "'${fic_src}' n'existe pas." >&2
	exit 1
}
[ -d "${fic_dest:=$2}" ] && fic_dest="${fic_dest%/}/${fic_src##*/}"

# taille du fichier source
size=$(stat --printf=%s "${fic_src}")
# nombre colonne 
cols=$(tput cols) 
maxcols=${cols}
# on enlève 6 caractères pour les [] et le montant du %
((cols-=6))

# lancmeent du process en background

cp "${fic_src}" "${fic_dest}" >& /dev/null &
exec 3< <(inotifywait -m -e modify -e close  "${fic_dest}" 2> /dev/null)

# tant que le process existe
while [ "$(jobs -r)" ]
do
  # si le fichier est ouvert on attend une modification
  lsof -p ${PID} "$fic_dest" >& /dev/null && read -u 3 texte
  # on affiche la progression
  affiche
done
exec 3<&-
# à nouveau affichage : l'affichage met du temps et il est possible que le job soit fini avant la fin de l'affichage, il faut donc la réactualiser
affiche
echo

$ rm debian-40r5-amd64-DVD-1.iso
$ time forum.ubuntu-fr.org/challenge/copie.sh dossier/debian-40r5-amd64-DVD-1.iso ~
[============================================================================================================================================================================>]100%

real    2m24.599s
user    0m56.648s
sys    1m30.062s


-- Lucid Lynx --

Hors ligne