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.

#1 Le 11/02/2010, à 23:05

Totor

[JEU] challenge bash #2

1265482796.png

[informations sur le jeu]

<<    challenge bash #2    >>

copie avec barre d'avancement

Le challenge consiste à réaliser un script le plus petit possible (en terme de quantité d'instructions) ayant pour objectif de copier un fichier en respectant les règles suivantes :
- le fichier destination pourra porter ou non le même nom
- une barre de progression sera affichée (l'affichage se fait en console)
- les outils destinés à la copie de fichiers et disposant de cette fonctionnalité sont proscrits (ex. le patch de cp, ...)

Vous trouverez également un script existant sur le net à base de awk -> pas la peine de le fournir wink

Le défi suprême : fournir une solution en une seule instruction : pas de pipe, pas de substitution de processus
Nous avons connaissance d'une telle solution avec juste une substitution de commande....

Facultativement, il pourra être intéressant de gérer :
- la conservation des droits .
- la copie multiple (dans ce cas, la progression unitaire suffira)

bonne réflexion...

EDIT : la qualité du code n'est pas représentative du nombre d'instructions ....

Dernière modification par Totor (Le 11/02/2010, à 23:11)


-- Lucid Lynx --

Hors ligne

#2 Le 11/02/2010, à 23:06

Totor

Re : [JEU] challenge bash #2

ma solution :

#!/bin/bash
affiche()
{
  new_size=$(stat --printf=%s "${fic_dest}")
  (( ${old_size} < ${new_size} )) && {
	  old_size=${new_size}
	  pct="$(printf '%3.0f' $((new_size*100/size)))"
	  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))

# pour verifier changement de taille
old_size=0

# lancmeent du process en background
cp "${fic_src}" "${fic_dest}" >& /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 && inotifywait -e modify -e close "${fic_dest}" >& /dev/null
  # on affiche la progression
  affiche
done
# à 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

et la version "une instruction" :

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

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


-- Lucid Lynx --

Hors ligne

#3 Le 12/02/2010, à 03:41

Yannou90

Re : [JEU] challenge bash #2

Bonjour a tous

Après les exploits de certains (dontonnedoitpasprononcerlenom) , je parle bien sur des gourous du bash et autres , et après avoir passer une nuit devant le pc a pleurer toutes les larmes de mon corps sur mes pauvres lignes de commandes , j'ai décidé comme çà , tout seul , de poster mon faux script :

Je sais d'avance que je n'ai aucunes chances mais ça ne fait rien ça en motivera d'autres lol

Bug : le "fichier" de destination est parfois plus gros que l'initial (nom de fichier,chemin ??) ?? hmm
Attention la copie s'effectue sans confirmation , la cible est ecrasée sad

Syntaxe :

[script] [origine] [destination]

Le code (et on ne rigole pas HEIN hmm ) :

#!/bin/bash
cp -Rf  "$1" "$2" &
POID_DEP=`du -s "$1" | awk '{ print $1 }'`
TOTAL_CP="0"                                 
while [ "$TOTAL_CP" -lt "100" ]
do
sleep 1
POID_ARR=`du -s "$2" | awk '{ print $1 }'`
TOTAL_CP=`echo "scale=2; $POID_ARR/$POID_DEP*100" | bc | cut -d'.' -f1`
while [ "$(echo $PROGRESS_BAR | wc -m )" != "$TOTAL_CP" ]
do
PROGRESS_BAR="$PROGRESS_BAR-"
done
clear
echo $TOTAL_CP'% |'$PROGRESS_BAR'>'
done
apt-get moo   #Un oeuf de pâques pour divertir un peu , commenter la ligne pour tuer le GNU
exit 0

Ben voila , c'est fait j'ai honte , faut que je me desinscrive du forum maintenant fait ch...

PS:bon ben j'ai un peu (j'ai pas arreter de toute la nuit) modifié mon script et j ai quand même trouver , j'y croyais pas big_smile

Edit(pour la 10e fois au moin): je sais que les matadords du bash sont venu jeter un oeil , pour le challenge 1 les posts pleuvaient , allez y messieurs faut basher avant que les pros débarquent , viteeeee

Dernière modification par Yannou90 (Le 12/02/2010, à 17:26)

Hors ligne

#4 Le 12/02/2010, à 12:25

Yannou90

Re : [JEU] challenge bash #2

Sinon ya ca mais c est de la triche cool :

#!/bin/bash
rsync -PHpEXogtav "$1" "$2"

J'ai pas le droit je sais mais je suis tout seul , allez les gars faut y croire quand les bashers(ca pete comme nom) vont debarquer on va pleurer , enfin moi j 'ai sorti les mouchoirs !!

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

Hors ligne

#5 Le 12/02/2010, à 18:24

AnsuzPeorth

Re : [JEU] challenge bash #2

C'est marrant ce petit jeu, ca permet d'utiliser des commandes que personnellement j'utilise jamais (getopts par exemple).

Pour le défit ultime, ça sera sans moi ... Je me suis donc appliqué pour le reste.

Je me suis servi de strace car je ne connais pas d'autres commande pour récupérer en temps réel (ou bien faire une boucle avec du ou ls).
Je ne me suis pas inspiré de l'exemple donnée en lien, je pige tjrs rien à awk (je dois faire un blocage !).

Sinon, comment mettre 200 fois plus de temps pour la même opération.

time cp 0m0.062s
time script 0m11.625s

La destination peut être un fichier, ce qui permet de renommer si on veut (copie unique) ou un dossier.

#!/bin/bash

car="→"
tro=" "
function Usage() 
{
echo "Usage : ./scritp.sh [-mtolcA] [destination] [fichier [fichier] [fichier]...]
Droits à copier: [defaut: -mto]
   -m    mode
   -t    timespand
   -o    ownership
   -l    links
   -c    context 
   -A    all"
exit
}

function Progress ()
{
poid=$(du -b "$1")
while read ligne
 do
      #sleep 0.2 #décommenter pour ralentir affichage
      # controle pour éviter erreurs dû à la dernière ligne de strace.
      [[ "$ligne" =~ [0-9]$ ]] && taille=$((taille + ${ligne#*= })) || continue
      pourcent=$(($taille * 100 / ${poid%	*}))
      if [ "${pourcent}" -ge 1 ]; then 
         for nb in $(seq $((20-${pourcent}/5))) 
             do
                trou="${trou}${tro}"
             done   
 
         for nb in $(seq $((${pourcent}/5)))
             do
                 prog="${prog}${car}"
             done 
         [ "${#pourcent}" = 1 ] &&  pourcent="0${pourcent}"
      else
         pourcent=00
         trou="                    "
      fi
      echo -en "    ${prog}${trou} --- ${pourcent} % --- ${poid%	*} Octets / $taille Octets\r" 
      unset prog trou
 done < <(strace -e write cp $droit_cp "$1" "$DEST" 2>&1)
 echo; echo
}

while getopts ":mtolcA" Option
  do
    case $Option in
        m)
         droit="${droit}mode,";;
        t)
         droit="${droit}timestamps,";;
        o)
         droit="${droit}ownership,";;
        l)
         droit="${droit}links,";;
        c)
         droit="${droit}context,";;
        A)
         droit="${droit}all,";;
        *)
         Usage;;
    esac
  done
shift $(($OPTIND - 1))

[ -n "$droit" ] && droit_cp="--preserve=${droit%,}"

if [ "${#@}" -gt 2 ] && [ ! -d "$1" ]; then
   echo -e "\n...[ERREUR]...\nPour copier plusieurs fichiers, le premier argument doit être un dossier.\n"
   Usage
fi

DEST=$1
shift
total=$(tail -n1 <<< "$(du -bch "$@")")
[ -z "$droit" ] && droit="[défaut]"
echo -e "\n Fichier(s) à copier vers ./${DEST##*/} → ${#@}\n  Droits copiés: ${droit%,}\n   ====== ${total%	*} au total ======\n"
  while [[ -n "$@" ]]
      do
        echo "   |→ ./${1##*/}"
        Progress "$1"
        shift
        unset prog trou pourcent poid taille
      done
exit

Les tabulations ne sont pas conservé lors de la copie du script, à rectifier donc. lignes 26, 42, 80,

 Fichier(s) à copier vers ./Projets → 2
  Droits copiés: [défaut]
   ====== 12M au total ======

   |→ ./Desmond Dekker - halfway to paradise.zip
    →→→→→→→→→→→→→→→→→→→→ --- 100 % --- 8070435 Octets / 8070435 Octets

   |→ ./genpuid.tar.gz
    →→→→→→→→             --- 43 % --- 4450350 Octets / 1916928 Octets

.
Une petite question au cadors/gurous :

 done <<< "$(strace -e write cp $droit_cp "$1" "$DEST" 2>&1)"
# OU BIEN
 done < <(strace -e write cp $droit_cp "$1" "$DEST" 2>&1)

Quelle forme est la plus appropriée ?
Je pense (mais pas sûr du tout), que la forme 1, strace est d'abord effectué puis envoyé dans le code.
Forme 2, c'est du "temps réel" ..... Je me trompe ?


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

Hors ligne

#6 Le 12/02/2010, à 19:53

nesthib

Re : [JEU] challenge bash #2

@AnsuzPeorth : la 2 est mieux selon moi, pas de conversion en chaîne de caractères avant d'envoyer sur l'entrée standard


GUL Bordeaux : GirollServices libres : TdCT.org
Hide in your shell, scripts & astuces :  applications dans un tunnelsmart wgettrouver des pdfinstall. auto de paquetssauvegarde auto♥ awk
  ⃛ɹǝsn xnuᴉꞁ uʍop-ǝpᴉsdn

Hors ligne

#7 Le 13/02/2010, à 13:33

AnsuzPeorth

Re : [JEU] challenge bash #2

La nuit porte conseils !

Je me répète, mais je pense qu'il serait bien de faire des catégories, débutant, intermédiaire, pro.
Je m'estime intermédiaire, c'est donc logique que je fournisse un meilleur code qu'un débutant, et un pro fera mieux que moi ! Normal !

Sinon, pour en revenir à nos moutons .... Le défit ultime, une seule substitution de commande, il n'est pas précisé si c'est une seule dans le code ou une seule pour toute l'exécution ?

Partant de ce principe, j'ai effectivement une seule substitution de commande, mais elle est exécutée un nombre de fois incalculable !

J'ai repris la même présentation de la progress-bar, mais j'ai pas mis toutes les options présentent dans mon premier code (pas la peine, suffit de copier/coller, modifier légérement les parties qui intéresses ! Ici, seule la principe de la progress est intéressante)

script.sh fichier_source dossier_destination
#!/bin/bash
fichier_source=$1
dossier_dest=$2
taille_source=
taille_copie=
car="→"
tro=" "
function CheckTaille ()
{
taille=$(stat -c %s "$1")
[ -n "$taille_source" ] && taille_copie=$taille || taille_source=$taille
}
CheckTaille "$fichier_source"
cp "$fichier_source" "$dossier_dest" &
sleep 0.2
while [[ "$taille_source" -gt "$taille_copie" ]]
do
CheckTaille "$dossier_dest/${fichier_source##*/}"
pourcent=$(($taille_copie * 100 / $taille_source))
    if [ "${pourcent}" -ge 1 ]; then
         n=$((20-${pourcent}/5))
         for ((i=1;i<=$n;i++)) 
             do
                trou="${trou}${tro}"
             done   
         n=$((${pourcent}/5))
         for ((i=1;i<=$n;i++)) 
             do
                 prog="${prog}${car}"
             done 
         [ "${#pourcent}" = 1 ] &&  pourcent="0${pourcent}"
      else
         pourcent=00
         trou="                    "
      fi
      echo -en "    ${prog}${trou} --- ${pourcent} % --- ${taille_source} Octets / ${taille_copie} Octets\r" 
      unset prog trou
 done
 echo; echo

exit

Dernière modification par AnsuzPeorth (Le 13/02/2010, à 13:47)


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

Hors ligne

#8 Le 13/02/2010, à 13:43

Yannou90

Re : [JEU] challenge bash #2

AnsuzPeorth a écrit :

La nuit porte conseils !

Je me répète, mais je pense qu'il serait bien de faire des catégories, débutant, intermédiaire, pro.
Je m'estime intermédiaire, c'est donc logique que je fournisse un meilleur code qu'un débutant, et un pro fera mieux que moi ! Normal !

100% d'accord

Moi je suis null et n'estime même pas avoir ma place sur le topic
Je ne dis pas ca parce que je suis un grand dépressif , hein , mais il est vrais que plusieurs catégories motiveraient peut-être plus de personne.
Par exemple mon faut bout de code a du en faire rire plus d'un mais je le comprend,a l'inverse des votres qui me tire plus une larme que m'inspire l'envie.
Ca fait 2 ans que je me suis mis a l'informatique,directement sur ubuntu,et suis autodidacte.C'est pour cela que je suis avec attention les pros du bash

Enfin je dit çà,mais la je suis tout seul comme un gros nul,je me sens tout petit petit big_smile
J'éspére que d'autres amateur oseront franchir le pas :
"C'est en tombant que l'on apprend à marcher !"

Hors ligne

#9 Le 13/02/2010, à 14:51

Totor

Re : [JEU] challenge bash #2

Bonjour,

Yannou90 a écrit :

[..]n'estime même pas avoir ma place sur le topic[..]

Bien au contraire ! L'intérêt est justement d'apprendre...

Yannou90 a écrit :

"C'est en tombant que l'on apprend à marcher !"

Exactement...
C'est en proposant des solutions que nous pourrons apporter des remarques à ton code (de façon constructif et non critique).

Donc en voici :
1. Pour connaitre la taille d'un fichier, il y a effectivement la commande du que tout le monde connait. Elle a tout de même un inconvénient : elle renvoie aussi le nom du fichier. Si l'on veut effectuer des calculs à partir de cette donnée, il faut à nouveau travailler sur la sortie de la commande du pour ne récupérer que la taille. C'est ce que tu as fait. C'est pour cela qu'il est préférable d'utiliser la commande stat à qui l'on peut préciser le format de sortie !
Dans notre cas :
stat --printf=%s <fichier>

2. En bash, il est possible de connaitre la taille d'une chaine de caractères sans utiliser la commande wc avec son option "-m". Il s'agit de la notation ${#variable}. Où variable est le nom de la variable qui contient la chaine dont tu souhaites connaitre le nombre de caractères. Cette notation existe aussi pour les tableaux mais elle indique le nombre d'éléments dans le tableau : ${#tableau[@]} (tableau étant le nom de la variable de type tableau). Et pour connaitre le nombre de caractères d'un élément du tableau : ${#tableau[indice]} : indice étant l'indice de l'élément dans le tableau.

3. Tu utilises l'instruction clear pour effacer la console. C'est inutile. Il existe deux options très pratiques à l'instruction echo
- -e : elle permet t'interpréter des caractères dit "d'échappement". L'un de ces caractères est \r. Ce dernier permet de revenir au début de la ligne.
- -n : elle indique à echo de ne pas effectuer un saut de ligne lorsqu'il a afficher ce que l'on lui demande

Je t'invite à consulter le man de cette instruction.
Par ailleurs, pour afficher du texte, il y a également l'instruction printf qui est un équivalent de echo -en

Enfin, à titre d'information : il existe aussi des caractères d'échapement VT100 permettant de (dé)placer le curseur là où on le souhaite dans la console.

AnsuzPeorth a écrit :

Sinon, pour en revenir à nos moutons .... Le défit ultime, une seule substitution de commande, il n'est pas précisé si c'est une seule dans le code ou une seule pour toute l'exécution ?

Partant de ce principe, j'ai effectivement une seule substitution de commande, mais elle est exécutée un nombre de fois incalculable !

Il s'agit d'une seule instruction pour tout le code et pour toute l'exécution wink

AnsuzPeorth a écrit :

Je me répète, mais je pense qu'il serait bien de faire des catégories, débutant, intermédiaire, pro.

probablement ... j'avoue avoir du mal à mesurer la difficulté d'un "challenge" ...


-- Lucid Lynx --

Hors ligne

#10 Le 13/02/2010, à 18:37

AnsuzPeorth

Re : [JEU] challenge bash #2

Totor a écrit :

Il s'agit d'une seule instruction pour tout le code et pour toute l'exécution wink

Je m'en doutais bien ... mais qui risque rien .... smile

Totor a écrit :

probablement ... j'avoue avoir du mal à mesurer la difficulté d'un "challenge" ...

Je parlais des résultats, meilleur chez les débutants, chez les intermédiaires. Une balises en début de post pour s'auto-évaluer.
Qd aux pros, difficile de juger, on ne peut pas être juge et partie. Peut être les participants aux jeux élisent leur gourou, le pro des pros !
Si la mayonnaise prends, bien sur !

En tout cas, ca part d'une bonne idée, on apprend à tous les étages.

Yannou90 a écrit:

    [..]n'estime même pas avoir ma place sur le topic[..]

Bien au contraire ! L'intérêt est justement d'apprendre...

    Yannou90 a écrit:

    "C'est en tombant que l'on apprend à marcher !"

Exactement...
C'est en proposant des solutions que nous pourrons apporter des remarques à ton code (de façon constructif et non critique).

Même si parfois on a l'impression de passer pour un imbécile, finalement, en sortie, on l'est moins, c'est le but wink


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

Hors ligne

#11 Le 13/02/2010, à 22:35

toto2006

Re : [JEU] challenge bash #2

arf un peu de couleur smile

#!/bin/bash

BAR="--------------------"
CAR="===================="
NORMAL="\033[0;39m" 
ROUGE="\033[1;31m"
VERT="\033[1;32m"

cp "$1" "$2" & 
T1=$(stat -c  '%s' "$1")
if (( $T1 == "0" )); then
	exit 0	
fi
FIN=0
for (( RES=0; FIN != 101  ;  RES=$( stat -c '%s' "$2") ))
do 
	VAL=$(($RES*100/$T1 )) 
	FIN=$(($VAL+1))
	FAIT=$(($VAL/5))
	RESTE=$((20-$FAIT))
	printf "${VERT}%.${FAIT}s${ROUGE}%.${RESTE}s${NORMAL} ($VAL%%) \r" $CAR $BAR 
done
echo

Hors ligne

#12 Le 13/02/2010, à 23:21

Khyl

Re : [JEU] challenge bash #2

Salut à tous,

voici ma version

#!/bin/bash
# Récupération du nombre de lignes du fichier de départ avec Sed
nb_lignes=$(sed -n '$=' $1)
# Création d'un fichier vide pour le fichier de sortie (cela me permet ensuite d'utiliser l'opérateur >> dans cut)
> $2
# Pour chaque ligne du fichier
for ((cpt_lignes=1; cpt_lignes <= nb_lignes; cpt_lignes++)) 
do
# on sélectionne la ligne à copier (ligne pointée par le compteur cpt_lignes)
cut -d'
' -f$cpt_lignes $1 >> $2
# affichage du % réalisé
echo -n $(($cpt_lignes*100/$nb_lignes))"% "
done
# on sort proprement
echo
exit 0

J'ai testé le script en l'enregistrant sous copie.sh et en faisant ./copie.sh ancien.html nouveau.html

Dernière modification par Khyl (Le 14/02/2010, à 01:30)

Hors ligne

#13 Le 13/02/2010, à 23:37

wido

Re : [JEU] challenge bash #2

Bonjour,
moyen de facilité:
bar-cat-n.gif
site: http://www.theiling.de/projects/bar.html

Hors ligne

#14 Le 14/02/2010, à 00:25

Yannou90

Re : [JEU] challenge bash #2

Bonjour ou Bonsoir

Merci Totor pour ces précision.
Le coup de echo -en "\r" je 'lai chercher mais pas ou il fallait roll
Pour stat j'avais trouvé mais je me suis entrainé sur des dossiers et fichiers car dans l'intitule : ...plusieurs fichiers... comme une truffe je l'ai pris pour un dossiers contenant plusieurs fichier
En gros j'ai fais ce script plus pour copier un dossier plutôt que comme l'indique l'intitulé "copie de fichier"
Plus qu'a refaire quoi tongue

Dernière modification par Yannou90 (Le 14/02/2010, à 00:25)

Hors ligne

#15 Le 14/02/2010, à 00:44

AnsuzPeorth

Re : [JEU] challenge bash #2

@Ph3nix_
synopsis: script <cible> <dest>
tu veux dire <source> <dest> ??? Chez moi, ca fonctionne po !
Rien ne se passe , puis affichage :

--- 0/100 --- 34M / 34M

@Khyl
C'est volontaire le défilement ligne par ligne dans le terminal ?

@toto2006
bravo, j'adore !
2 nouveautés pour moi.

printf "%.1s" deux

vraiment pratique !

(( RES=0; FIN != 101  ;  RES=$( stat -c '%s' "$2") ))

par contre là,je connaissais ((i=0;i<=10;i++)), mais je ne savais pas qu'on pouvait utiliser une variable exterieur au doubles-parenthèses comme délimiteur ....(je dis pas de bêtises, le paramètre n°2 sert tjrs de délimiteur ?)
Ca reviens à

while [[ $FIN != 101 ]]
do
RES=$( stat -c '%s' "$2") )
....
....

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

Hors ligne

#16 Le 14/02/2010, à 00:56

Khyl

Re : [JEU] challenge bash #2

@AnsuzPeorth

Ce que j'affiche, c'est le pourcentage de copie réalisée (vu qu'il est demandé de faire une barre de progression). Comme j'enregistre ligne par ligne d'un fichier sur l'autre, effectivement ça implique que ça met à jour le compteur à chaque ligne. Sur un gros fichier, ça peut être énervant. wink
J'ai fait le programme à titre d'exercice, en le testant sur un fichier texte de 450 lignes.

Dernière modification par Khyl (Le 14/02/2010, à 01:09)

Hors ligne

#17 Le 14/02/2010, à 01:13

AnsuzPeorth

Re : [JEU] challenge bash #2

40 %
40 %
41 %
41 %
41 %
41 %
41 %
41 %
41 %
41 %
42 %
42 %
42 %
42 %
42 %
42 %
42 %
42 %
43 %
43 %
43 %

C'est le résultat que j'ai chez moi, comme le préconise totor dans un post précèdent, printf ou echo -en pour afficher sur la même ligne. A moins que ce soir l'affichage voulu !


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

Hors ligne

#18 Le 14/02/2010, à 01:33

Khyl

Re : [JEU] challenge bash #2

Ok merci pour l'info AnsuzPeorth. J'avais pas fait gaffe qu'il fallait tout mettre sur une ligne. J'ai rajouté l'option -n à mon echo.

Dernière modification par Khyl (Le 14/02/2010, à 01:51)

Hors ligne

#19 Le 14/02/2010, à 03:13

sputnick

Re : [JEU] challenge bash #2

Salut,

j'ai une solution en bash, mais c'est plus lent que le awk donné en lien. Juste pour un "proof of concept". Je n'utilise pas strace, mais je parse le fichier donné en argument ligne par ligne :

#!/bin/bash
# Codé par sputnick 02/2010

if [[ ! $2 ]]; then
    echo >&2 -e "$0 <source file> <target file>"
    exit 1
fi

export LANG=C
sourcefilesize=$(stat -c %s "$1")
compteur=$sourcefilesize
percent=0

:>"$2"
tput bold

while read a; do
    destfilesize=$(stat -c %s "$2")
    percentb=$(bc <<< "scale=2; $destfilesize/$sourcefilesize")
    printf -v percent "%.0f" ${percentb#*.}
    printf "%3d%% [" ${percent}
    eval printf '%.0s=' {0..$percent}
    printf ">%*c\r" $((100 - percent)) ']'
    echo "$a" >> "$2"
    ((compteur--))
done < "$1"

tput sgr0
echo

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

Hors ligne

#20 Le 14/02/2010, à 15:50

Yannou90

Re : [JEU] challenge bash #2

Bonjour

NIVEAU : amateur , auto-didacte depuis 2 ans (je vais le dire comme çà c'est clair tongue )

Comment fait on si on estime devoir corrige ? On Re-post , ou on reedite notre post initial ??

Nouvelle version avec prise en compte des remarques de Totor , plus precis sur un gros fichier :

-affiche le pourcentage
-affiche la progression
-affiche le poid
-affiche la vitesse |->> calculée toute les secondes : la vitesse affichee n'est pas relle mais moyenne et par seconde

Y a des chances que je repasse par la pour les option sur les droits et la copie multiple ...

Utilisation :
[script] [source] [destination]

Apparrence :

Progression : 41% [::::>......] Poid : (300056576/731365376)kio Vitesse : 23081275 kio/s
Progression : 100% [::::::::::>] Poid : (731365376/731365376)kio Vitesse : 10018703 kio/s Copie effectuée

Script:

#!/bin/bash
cp "$1" "$2" &
POID_DEP=`stat -c "%s" "$1"`
TOTAL_CP="0" 
TEMPS_PASS="0"
NO_BAR=".........."                                
while [ "$TOTAL_CP" -lt "100" ]
do
	sleep 1

	POID_ARR=`stat -c "%s" "$2"`
	TOTAL_CP=$(($POID_ARR*100/$POID_DEP))
	TOTAL_CP_BAR=$(($TOTAL_CP/10))
	TEMPS_PASS=$(($TEMPS_PASS+1))
	VITESSE_CP=$(($POID_ARR/$TEMPS_PASS))	
	while [ "${#PROGRESS_BAR}" != "$TOTAL_CP_BAR" ]
	do
		PROGRESS_BAR="$PROGRESS_BAR:"
		NO_BAR=`echo $NO_BAR | sed -e  's/.//'`
	done
	echo -en "\r"'Progression : '$TOTAL_CP'% ['$PROGRESS_BAR'>'$NO_BAR'] Poid : ('$POID_ARR'/'$POID_DEP')kio Vitesse : '$VITESSE_CP' kio/s '
done
echo "Copie effectuée"
exit 0

Hors ligne

#21 Le 14/02/2010, à 17:54

Ph3nix_

Re : [JEU] challenge bash #2

Voici mes 2 version:

Une première version lente (donc inutile) avec read:
Synopsis <fichier_source> <fichier_cible>

#!/bin/bash
TOTAL=( $(wc -l "$1") )
BAR="==================="
:> "$2"

while read i;do
	echo "$i" >> "$2"
	printf "\r$((p= n++*100 / TOTAL[0]))/100 [${BAR:0:(( p / 5))}>"
done < "$1"
printf "]\n"

Voici une seconde version très rapide qui va appeller une fonction récursivement qui va afficher toutes les 0.1s l'état d'avancement jusqu'a la fin de la copie
Synopsis <fichier_source> <fichier_cible>

#!/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]} -ne ${S_TOTAL[0]} ] && sleep 0.1 && fct "$1" || echo "]"; }

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

exemple:

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

Dernière modification par Ph3nix_ (Le 14/02/2010, à 17:55)


Hiroshima 45 / Chernobyl 86 / Windows '95

Hors ligne

#22 Le 14/02/2010, à 21:11

Yannou90

Re : [JEU] challenge bash #2

Re Bonjour

Edit : ajout du temps restant en seconde , bon la c'est bon j'arrete !

Çà y est , j'ai tout de même terminé.Bon c'est mon dernier post jusqu'au résultat,j'ai hate de voir LA solution!

Nouveau script :

-NE PAS passer de fichiers contenant des espaces vides sinon çà part en sucette
-NE PAS passer de dossier dans la liste a copier SAUF en dernier :fichier fichier fichier DOSSIER

Utilisation :

[script] [source] [cible] ou source et cible sont des noms de FICHIER
ou
[script] [fichier] [fichier]  [fichier]  [fichier] ... [dossier]

En cas de copie multiple si le dernier argument n'est pas un dossier le script s'arrete

Pour les droits : lancer le script comme mentionné ci-dessus , au démarage il sera demandé quels options passer a cp , je me suis pas fouler j'avoue , pour les options voir man cp

Enfin le script:

#!/bin/bash

LISTE_CP="$*"
NOMBRE_ARG="$#"

function ARG_SP_CP()
{
echo "Argument a passer a 'cp' ( comme si passé directement a 'cp') ; laisser vide si aucun :"
read ARG_CP
}

function PROGRESS_BAR_CP()
{
cp $ARG_CP "$1" "$2" &
POID_DEP=`stat -c "%s" "$1"`
TOTAL_CP="0" 
TEMPS_PASS="0"
PROGRESS_BAR=
NO_BAR=".........."                                
while [ "$TOTAL_CP" -lt "100" ]
do
	sleep 0.2

	POID_ARR=`stat -c "%s" "$2"`
	TOTAL_CP=$(($POID_ARR*100/$POID_DEP))
	TOTAL_CP_BAR=$(($TOTAL_CP/10))
	TEMPS_PASS=`echo "scale=1; $TEMPS_PASS+0.2" | bc`
	VITESSE_CP=`echo "scale=1; $POID_ARR/$TEMPS_PASS" | bc`
        TEMPS_REST=`echo "($POID_DEP-$POID_ARR)/$VITESSE_CP" | bc`
	while [ "${#PROGRESS_BAR}" != "$TOTAL_CP_BAR" ]
	do
		PROGRESS_BAR="$PROGRESS_BAR:"
		NO_BAR=`echo $NO_BAR | sed -e  's/.//'`
	done
	echo -en "\rProgression : "$TOTAL_CP'% ['$PROGRESS_BAR'>'$NO_BAR'] Poid : ('$POID_ARR'/'$POID_DEP')kio Vitesse : '$VITESSE_CP' kio/s Temps restant : '$TEMPS_REST' secondes'
done
echo -en "\nLa copie de : "$1"\nVers : "$2"\nEst terminée !\n\n"
return
}

if [ "$NOMBRE_ARG" != "2" ]
then
	DOSSIER_CIBLE=`echo $LISTE_CP | tr " " "\n" | tail -n 1`
	LISTE_CP_SOURCE=`echo $LISTE_CP | tr " " "\n" | sed '$d'`
	TEST_DEST=`file -b "$DOSSIER_CIBLE"`
	if [ "$TEST_DEST" != "directory" ]
	then
		echo "En cas de copie multiple le dernier argument doit être un dossier !"
		exit
	fi
	ARG_SP_CP
	for i in $LISTE_CP_SOURCE
	do
	CIBLE_CP="$DOSSIER_CIBLE/`echo $i | sed 's|\(.*\)/|\1#|' | cut -d# -f2`"
	PROGRESS_BAR_CP "$i" "$CIBLE_CP"
	done
	exit 0
fi
ARG_SP_CP
PROGRESS_BAR_CP "$1" "$2"
exit 0

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

Hors ligne

#23 Le 14/02/2010, à 21:40

Khyl

Re : [JEU] challenge bash #2

Je dirais en voyant ce que chacun produit qu'au final, nous sommes tous gagnants dans un tel jeu car nous progressons par nos recherches et par la lecture des autres scripts. C'est une initiative intelligente et de bien bonne augure. Je suis un débutant en bash et j'apprends beaucoup ces derniers jours smile

Merci Totor et merci à tous ceux qui se lancent dans le jeu quelque soit leur niveau.

Hors ligne

#24 Le 14/02/2010, à 22:28

nesthib

Re : [JEU] challenge bash #2

Khyl a écrit :

Je dirais en voyant ce que chacun produit qu'au final, nous sommes tous gagnants dans un tel jeu car nous progressons par nos recherches et par la lecture des autres scripts. C'est une initiative intelligente et de bien bonne augure. Je suis un débutant en bash et j'apprends beaucoup ces derniers jours smile

Merci Totor et merci à tous ceux qui se lancent dans le jeu quelque soit leur niveau.

C'était le but de ce challenge smile De faire découvrir le bash et plus généralement le scripting. À titre perso je proposerai des challenges qui ont vocation d'être utiles et directement utilisables et Totor plus des challenges qui montrent des points techniques et font découvrir les entrailles de bash.

Pour tenir le rythme et faire vivre le challenge bash, nous sommes toujours à la recherche de propositions de challenges. N'hésitez pas à les envoyer.


GUL Bordeaux : GirollServices libres : TdCT.org
Hide in your shell, scripts & astuces :  applications dans un tunnelsmart wgettrouver des pdfinstall. auto de paquetssauvegarde auto♥ awk
  ⃛ɹǝsn xnuᴉꞁ uʍop-ǝpᴉsdn

Hors ligne

#25 Le 14/02/2010, à 23:05

sputnick

Re : [JEU] challenge bash #2

Version pour de vrai ^^

Bench :

$ time bash progressbar-time.bash /tmp/locatedbp /tmp/sfzaaaaaaqzwwx
99% [====================================================================================================>]

real    0m18.161s
user    0m0.137s
sys     0m2.873s
$ time cp -af /tmp/locatedbp /tmp/sfzaaaaaaqzwwx

real    0m18.223s
user    0m0.037s
sys     0m2.517s

#!/bin/bash
# Codé par sputnick 02/2010

[[ ! "$2" || ! -f "$1" ]] && { echo >&2 -e "$0 <source file> <target file>"; exit 1; }

read sourcefilesize < <(stat -c %s "$1")
LANG=C percent=0

:>"$2"
\cp -af "$1" "$2" & cpPid=$!
tput bold

while kill &>/dev/null -0 $cpPid; do
	read destfilesize < <(stat -c %s "$2")
	percent=$((destfilesize*100/sourcefilesize))
	printf "%3d%% [" ${percent}
	eval printf '%.0s=' {0..$percent}
	printf ">%*c\r" $((100 - percent)) ']'
	sleep .3
done

perl -le'print"100% [","="x100,">]";'
tput sgr0
echo

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


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

Hors ligne