Communauté francophone des utilisateurs d'Ubuntu
Les Ubuntu-partys sont l'occasion pour beaucoup d'entre vous d'acquérir les goodies Ubuntu-fr faits par nos petites mains avec amour.
Pour tous les autres, fini le désespoir de les manquer
Il est désormais possible de vous procurer l'objet de votre choix grâce à la boutique en ligne, commune à Framasoft et Ubuntu-fr. Vous pourrez déjà y trouver mugs, t-shirts et, bien sûr, les Framakey Ubuntu-fr Remix.
Bonjour,
Je viens de réaliser un petit script qui permet de surveiller avec une jauge l'avancement de la copie d'un fichier.
Extrait de ma console :
$ gcp pres.tex pres.tex2 0 100% |===========================================================| Done.
Il détecte automatiquement le nombre de colonnes de votre terminal et affiche une barre de progression.
Pour le moment, ce script ne copie que le premier argument vers le deuxième, et non pas tous les arguments vers le dernier. N'utilisez donc pas ce script sous la forme « gcp * un_répertoire/ »
« à quoi ça sert ?
--- Ben, à vous de trouver »
#!/bin/bash
# __ _ __
# ____ __________ _____ / /_ (_)________ _/ / _________
# / __ `/ ___/ __ `/ __ \/ __ \/ / ___/ __ `/ / / ___/ __ \
# / /_/ / / / /_/ / /_/ / / / / / /__/ /_/ / / / /__/ /_/ /
# \__, /_/ \__,_/ .___/_/ /_/_/\___/\__,_/_/ \___/ .___/
#/____/ /_/ /_/
# by Pabix (mortgat ... GMAIL ... com)
# BSD License
#
# Redistribution and use in source and binary forms, with or
# without modification, are permitted provided that the following
# conditions are met:
#
# * Redistributions of source code must retain the above
# copyright notice, this list of conditions and the following
# disclaimer.
#
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials
# provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
# THE POSSIBILITY OF SUCH DAMAGE.
DEBUG=0
# _ _ _
# __ _| | ___ | |__ __ _| |___
# / _` | |/ _ \| '_ \ / _` | / __|
#| (_| | | (_) | |_) | (_| | \__ \
# \__, |_|\___/|_.__/ \__,_|_|___/
# |___/
# Success message
FINISHED="Done"
# Message when copy aborted
FINISHEDERROR="Error"
# Calculates number of available columns on the terminal
COLUMNS=$( stty -a | head -n 1 | awk '{print $7}' | rev | cut -b 2- | rev )
# Calculates width of gauge using last value
COLS=$((${COLUMNS} -${#FINISHED} - 5))
# Default refresh delay
DELAY=0.1
# Echo ($2), repeated ($1) times
function multiecho(){
debug $1 columns times $2
for i in $(seq 1 $1)
do
echo -n -e "$2"
done
}
# Display help
function usage(){
cat << EOF
gcp [options] source destination
copy source file to destination file using a graphical gauge.
Only ONE source file is allowed at a time.
options:
-c (n) : use (n) columns to display
-d : use debug options
-h : display help
-r (t) : use (t) seconds refresh delay
EOF
}
# _ _
# ___ _ __ | |_(_) ___ _ __ ___
# / _ \| '_ \| __| |/ _ \| '_ \/ __|
#| (_) | |_) | |_| | (_) | | | \__ \
# \___/| .__/ \__|_|\___/|_| |_|___/
# |_|
# Parsing options
while getopts "c:dr:h" option
do
case $option in
c)
COLS=$OPTARG
;;
d)
DEBUG=1
;;
r)
DELAY=$OPTARG
;;
h)
usage
exit 0
;;
*)
;;
esac
done
shift $((OPTIND-1));
# Checks number of options correct
if [[ $# -ne 2 ]]
then
usage
exit 1
fi
sourcefile=$1
if [[ ! -e "$sourcefile" ]]
then
usage
exit 1
fi
destinationfile=$2
# Checking that destination is a regular file.
if [[ -d "$destinationfile" ]]
then
destinationfile=${destinationfile%\/}"/"$(basename ${sourcefile})
fi
# Warning if destination exists
if [[ -e "$destinationfile" ]]
then
echo WARNING: $destinationfile exists!
fi
shift 2
# _ _
# __| | ___| |__ _ _ __ _
# / _` |/ _ \ '_ \| | | |/ _` |
#| (_| | __/ |_) | |_| | (_| |
# \__,_|\___|_.__/ \__,_|\__, |
# |___/
DEBUGFILE=`tempfile`
if [[ "$DEBUG" = "1" ]]
then
function debug(){
echo $@ >> $DEBUGFILE
}
else
function debug(){
:
}
fi
debug $COLS columns
debug source file : $sourcefile
debug destination : $destinationfile
# _ _ _
# __| (_)___ _ __ | | __ _ _ _
# / _` | / __| '_ \| |/ _` | | | |
#| (_| | \__ \ |_) | | (_| | |_| |
# \__,_|_|___/ .__/|_|\__,_|\__, |
# |_| |___/
# Backspace
RET_ARR="\010"
# sufficient backspacing to go back
KILLLINE=${RET_ARR}${RET_ARR}
for i in $(seq 1 $COLS)
do
KILLLINE=${KILLLINE}${RET_ARR}
done
# Rule
echo -n "0"
multiecho $(($COLS-4)) " "
echo '100%' ;
# Gauge
echo -n "|"
multiecho $COLS " "
echo -n "|"
# _
# _ __ ___ __ _(_)_ __
#| '_ ` _ \ / _` | | '_ \
#| | | | | | (_| | | | | |
#|_| |_| |_|\__,_|_|_| |_|
#
# Indicator of working cp
INDFILE=`tempfile`
# Invoking cp
(nice cp "$sourcefile" "$destinationfile" ; rm $INDFILE) &
# Grabbing source size
SOURCEFILESIZE=$(($(ls -o "$sourcefile" | awk '{print $4}') + 1))
DESTFILESIZE=0
debug source file size : $SOURCEFILESIZE
# MAIN LOOP
while [[ -e "$INDFILE" ]]
do
sleep $DELAY
# Grabbing destination size
DESTFILESIZE=$(($(ls -o "$destinationfile" | awk '{print $4}') + 1))
PERCENTAGE=$(($COLS * $DESTFILESIZE / $SOURCEFILESIZE ))
# Displaying gauge
echo -e -n $KILLLINE"|"
multiecho $PERCENTAGE "="
done
# _ _
# _____ _(_) |_
# / _ \ \/ / | __|
#| __/> <| | |_
# \___/_/\_\_|\__|
#
# Checks sizes of destination and source
DESTFILESIZE=$(($(ls -o "$destinationfile" | awk '{print $4}') + 1))
if [[ "$DESTFILESIZE" != "$SOURCEFILESIZE" ]]
then
echo -e "\033[30m!!! $FINISHEDERROR.\033[0m"
else
echo "| $FINISHED."
fi
# Debugfile is empty if no debug option specified
cat $DEBUGFILE
rm $DEBUGFILEEn vous souhaitant une bonne utilisation
EDIT : blindé contre l'utilisation avec trop d'arguments pour le moment
LOG de corrections
* 11/12/2006 -- Correction : protection des noms de fichiers avec espaces
Benoit
Dernière modification par pabix (Le 13/12/2006, à 17:56)
Hors ligne
ben, de rien !
Hors ligne
un peu de feedback peut-être ? Qu'aimeriez-vous voir en plus ?
Benoit
Hors ligne
Je n'ai pas essayé ton script mais visiblement il ne supporte pas la copie de repertoire, et ne permet pas de passer des arguments à cp (-i -r -f...)
Tu pourrais peut être modifier les sources du cp original pour rajouter cette option non ?
Hors ligne
en effet, il ne supporte pas -i, -r, -f pour la simple raison qu'il ne supporte qu'un seul fichier à la fois : je pars du principe que la récursivité n'est pas nécessaire, et que "forcer" ou "demander s'il faut continuer", en copiant un seul fichier on se trompe moins.
Ensuite, oui, il faudrait supporter la copie de répertoire, mais peut-être faire un script qui appelle celui-là plusieurs fois, je ne sais pas...
Benoit
Hors ligne
Utilisé avec succès sur un gros fichier de plusieurs Go ![]()
Falait faire ça en ligne de commande, du coup j'en ai profité pour tester.
Le support des arguments / fichiers multples serait en effet un grand plus.
Sinon... Je suis très intéréssé par la gestion de la gauge, mais mon niveau de bash est assez faible, et je suis un peu perdu. Est ce que tu aurais une version... Standalone ? ![]()
(merci d'avance si oui, lol)
Hors ligne
Salut Tigriss.
Il y a plusieurs choses pour la jauge :
1. Détection du nombre de colonnes du terminal :
COLUMNS=$( stty -a | head -n 1 | awk '{print $7}' | rev | cut -b 2- | rev )stty -a te fournit des infos sur le terminal, seul le 7e champ de la première ligne est intéressant, et pour avoir tous les caractères sauf le dernier (un point-virgule), j'inverse, je coupe à partir du 2e caractère et je réinverse.
(Détail ![]()
$ stty -a
speed 38400 baud; rows 70; columns 179; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V;
flush = ^O; min = 1; time = 0;
-parenb -parodd cs8 -hupcl -cstopb cread -clocal -crtscts
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl -ixon -ixoff -iuclc -ixany -imaxbel iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke
$ stty -a | head -n 1
speed 38400 baud; rows 70; columns 179; line = 0;
$ stty -a | head -n 1 | awk '{print $7'}
179;
$ stty -a | head -n 1 | awk '{print $7'} | rev
;971
$ stty -a | head -n 1 | awk '{print $7'} | rev | cut -b 2-
971
$ stty -a | head -n 1 | awk '{print $7'} | rev | cut -b 2- | rev
1792. On enlève un certain nombre (en l'occurence, 2 pour les extrémités |==
, 1 pour une espace après, 4 pour le "Done" et 1 pour le point après Done, ce qui fait
COLS=$((${COLUMNS} -${#FINISHED} - 5))${#VAR} fournit la longueur de la variable, en l'occurrence DONE
3. J'ai une fonction "multiecho" qui permet de répéter un caractère. Soit un égal, soit une espace, soit un retour arrière en l'occurrence.
function multiecho(){
for i in $(seq 1 $1)
do
echo -n -e "$2"
done
}elle s'appelle comme suit : « multiecho 15 "Toto" »
ça affiche "TotoTotoTotoTotoTotoTotoTotoTotoTotoTotoTotoTotoTotoTotoToto"
4. J'ai un caractère ASCII permettant de faire un retour en arrière (voir man ascii) : c'est le caractère \010 ou \b ou \x08 ; il faut appeler echo avec l'option -e pour que ça supporte ces caractères. À noter qu'il ne faut jamais retourner à la ligne : il faut appeler echo avec l'option -n à chaque fois. Il faut noter aussi qu'un retour en arrière permet uniquement de déplacer le curseur, PAS d'effacer le caractère courant : tu peux pour cela envoyer "\010 \010" (retour arrière, espace, retour arrière)
5. Ma variable $KILLLINE est composée de plein de retours arrière, suffisamment pour retourner en début de ligne. Je n'efface rien car je n'en ai pas besoin : ma jauge ne descendra jamais.
6. Au début, je dessine la jauge (les deux extrémités).
Dans la boucle, j'envoie $KILLLINE, je redessine la première extrémité et dessine autant de = qu'il le faut (en fonction de valeurs que je récupère, et je fais une bête règle de trois avec le nombre de colonnes).
Pour éviter la division par 0 dans les tailles de fichiers, j'ai pris le soin de rajouter 1 à chaque taille : ça ne fausse pas beaucoup l'affichage ![]()
Benoit
Dernière modification par pabix (Le 12/12/2006, à 10:12)
Hors ligne
Une autre façon de récupérer le nombre de colonnes avec moins de pipes :
stty -a | grep columns | cut -d " " -f 7 | grep -o [0-9]*
Avec le premier grep, tu récupères uniquement la ligne qui t'intéresse.
Avec le cut tu définis l'espace comme un délimiteur de champs et tu prends le 7ème champs ("80;" par exemple).
Avec le 2ème grep tu ne récupères que les chiffres, ce qui supprime le ";"
Voilà ![]()
Hors ligne
c'est vrai que le "grep -o [0-9]*" j'y ai pas pensé. Par contre, je préfère mon head et awk pour récupérer le 7e champ, pour être certain d'avoir une seule ligne.
Hors ligne
Sympa le script :-)
Je ne m'étais jamais penché sur comment faire correctement une barre de chargement mais la tienne m'a l'air plutôt pas mal.
Merci !
Dernière modification par gapz (Le 12/12/2006, à 20:41)
Hors ligne
gapz : oui, j'aime bien ma pitite barre, sauf que si on redimensionne le terminal, ça marche plus, et qu'il faut pas qu'une sortie d'erreur ne vienne perturber le schmilblick ![]()
Benoit
Hors ligne
Il y a t'il moyen de faire quelquechose avec "pv" ?
genre:
#!/bin/sh
SIZE=`ls -la $1 |awk '{print $5}'`
dd if=$1 |pv -s $SIZE | dd of=$2Ce qui donne un truc dans le genre pendant le transfert:
./toto Nom_de_code_Linux_-_Documentaire_ARTE_.avi tutu.avi 207MO 0:00:15 [17,6MO/s] [=========================================================== > ] 80% ETA
Par contre l'inconvénient sur cp doit être la lenteur...
- dd est a priori + lent que cp (Il y a peut etre mieux que dd pour cela ? )
- multiplier les pipes doit pas aider non plus pour la rapidité...
Hors ligne
Je lis que cp aurait une option non documentée permettant d'afficher une barre de progression.
Je ne peux pas essayer, quelqu'un peut-il confirmer ?
cp -g fichier1 fichier2
Le patch originel permettant d'avoir cette fonction est là :
http://www.mail-archive.com/bug-coreuti … 00610.html
Hors ligne
On peut aussi utiliser scp en local
la ligne de commande est un peu plus longue mais on peut utiliser le récursif etc.
scp [opt] [path]/fichier localhost:[path]/fichier
Hors ligne
Le cp et le mv dans gentoo peuvent afficher une barre de progression. Malheureusement cette fonctionnalité n'a pas encore été acceptée dans les sources officielles du projet gnu.
J'ai donc compilé depuis les sources gentoo et ça marche !
Les sources et le patch sont là : (j'ai préféré prendre la version 5.96 pour coller avec edgy)
http://mirror.in.th/gentoo/distfiles/co … 96.tar.bz2
http://mirror.in.th/gentoo/distfiles/co … .2.tar.bz2
Voilà comment j'ai procédé :
cd wget http://mirror.in.th/gentoo/distfiles/coreutils-5.96.tar.bz2 wget http://mirror.in.th/gentoo/distfiles/coreutils-5.96-patches-1.2.tar.bz2 tar xvjf coreutils-5.96.tar.bz2 tar xvjf coreutils-5.96-patches-1.2.tar.bz2 cd coreutils-5.96/src patch < ../../patch/generic/001_all_coreutils-gen-progress-bar.patch cd .. ./configure fakeroot make
J'ai fait ensuite un petit test :
cd
cd coreutils-5.96/src
./cp -g grosfichier grosfichier_copie
ça affiche ça :
grosfichier | 8% | 700 MiB | 6,0 MiB/s | ETA
Je n'ai pas procédé à l'installation, car là j'ai peur de m'aventurer trop loin. Je doute que cela soit sans danger de faire un sudo checkinstall ou make install ...
Je serais tenté de copier à la main les nouveau cp et mv pour remplacer les anciens. Ou alors de les copier sous un autre nom et d'utiliser un alias...
Qu'en pensez-vous ?
Dernière modification par Enjoy Aspirin (Le 14/12/2006, à 21:00)
Hors ligne
cat 001_all_coreutils-gen-progress-bar.patch
Upstream has been contacted about this a few times ... they dont want progress bars in mv/cp: http://lists.gnu.org/archive/html/bug-coreutils/2003-08/msg00114.html http://lists.gnu.org/archive/html/bug-coreutils/2003-09/msg00083.html http://lists.gnu.org/archive/html/bug-coreutils/2003-09/msg00084.html but they don't seem to mind a general util ... add this to future patchset: http://lists.gnu.org/archive/html/bug-coreutils/2003-09/msg00101.html http://lists.gnu.org/archive/html/bug-coreutils/2004-02/msg00071.html (...)
Hors ligne
Salut,
bonne initiative. Malheuresement, ça marche pas sur mon WD MyBook World II (BusyBox), car les commandes "rev" et "tempfile" n'existent pas... Je te serais très reconnaissant si tu pouvais me donner une version sans ces deux commandes.
Blacklord
Super déterrage de sujet! le dernier message date de décembre 2006, je ne sais pas si l'auteur vient encore consulter ce sujet pour y répondre...
Hors ligne
si si !
Pour Blacklord : rev et tempfile ne sont pas forcément nécessaires. On doit pouvoir spécifier un nom du genre /tmp/TEMP1 et le supprimer après. Rev peut être remplacé sans doute par awk je ne sais trop comment.
Dernière modification par pabix (Le 24/05/2009, à 13:09)
Hors ligne
Pour se passer de rev, on peut utiliser sed :
COLUMNS=$( stty -a | head -n 1 | awk '{print $7}' | sed "s/;$//" )
Bonjour,
xman a écrit:
Pour se passer de rev, on peut utiliser sed :
COLUMNS=$( stty -a | head -n 1 | awk '{print $7}' | sed "s/;$//" )
ou bien, tout simplement :
COLUMNS=$(tput cols)
EDIT :
Uggy a écrit:
Il y a t'il moyen de faire quelquechose avec "pv" ?
genre:Code:
#!/bin/sh SIZE=`ls -la $1 |awk '{print $5}'` dd if=$1 |pv -s $SIZE | dd of=$2Ce qui donne un truc dans le genre pendant le transfert:
Code:
./toto Nom_de_code_Linux_-_Documentaire_ARTE_.avi tutu.avi 207MO 0:00:15 [17,6MO/s] [=========================================================== > ] 80% ETAPar contre l'inconvénient sur cp doit être la lenteur...
- dd est a priori + lent que cp (Il y a peut etre mieux que dd pour cela ? )
- multiplier les pipes doit pas aider non plus pour la rapidité...
Sans utiliser dd ou cp, juste les mécanismes de redirection :
pv -s $(stat --printf=%s "$1") <"$1" >"$2"
où $1 = fichier source et $2 fichier destination
Dernière modification par Totor (Le 16/06/2009, à 21:15)
En ligne
Cool le truc avec les redirections !
Par contre ce n'est valable qu'avec un seul fichier, j'aurais bien aimé pouvoir l'intégrer à mon scripts de backup de mes répertoires (cp -Rf donc) sensibles ![]()
Dernière modification par steph33560 (Le 05/07/2009, à 09:31)
Hors ligne
steph33560 a écrit:
Cool le truc avec les redirections !
Par contre ce n'est valable qu'avec un seul fichier, j'aurais bien aimé pouvoir l'intégrer à mon scripts de backup de mes répertoires (cp -Rf donc) sensibles
Pour effectuer un traitement de masse, il faut exploiter find.
Cela dit, il y a un inconvénient majeur à l'utilisation de pv : les droits et utilisateurs/groupes ne sont pas conservés.
Mais cela peu être comblé par un peu de script (mais uniquement en root).
En ligne
Totor a écrit:
steph33560 a écrit:
Cool le truc avec les redirections !
Par contre ce n'est valable qu'avec un seul fichier, j'aurais bien aimé pouvoir l'intégrer à mon scripts de backup de mes répertoires (cp -Rf donc) sensiblesPour effectuer un traitement de masse, il faut exploiter find.
Cela dit, il y a un inconvénient majeur à l'utilisation de pv : les droits et utilisateurs/groupes ne sont pas conservés.
Mais cela peu être comblé par un peu de script (mais uniquement en root).
Ourch.... non merci !
Je crois dans ce cas que je vais garder mon tar incrémentiel tout seul ...
Hors ligne