#1 Le 19/04/2011, à 12:23
- lylambda
Script bash : traiter successivement les éléments d'une sortie
Bonjour,
Débutant et autodidacte au bash, je bloque actuellement sur l'amélioration d'un de mes scripts (Copy-Flash).
La première partie du code remanié me permet de récupérer une liste de nombre sous la forme
17
23
24
Chaque entrée correspondant à un fichier dans une arborescence du type /dossier1/dossier2/XX, je souhaiterais ensuite les utiliser respectivement (en parallèle ou successivement) pour effectuer des opérations au sein d'une boucle :
- définition d'une variable à chacun en récupérant le nom du fichier dans ses propriétés
- boucle testant l'augmentation de la taille du fichier
- sortie de boucle lorsque la taille du fichier est stable
- copie et renommage du fichier
Actuellement, mon script fonctionne parfaitement avec une seule entrée. Mais est-il possible d'effectuer la même procédure sur chaque élément de la liste ?
Pour être plus clair, voici le script fonctionnel en sélectionnant un seul fichier :
#!/bin/bash
#########################################################################################################
# Description: Permet de sauvegarder les videos flash en cours dans le navigateur. #
# Dépendances: grep; zenity; awk; #
# Auteurs: lylambda; bece (amélioration) #
# Version: Copy-Flash 0.4 #
# Licence: gpl #
# http://forum.ubuntu-fr.org/viewtopic.php?id=424080 #
#########################################################################################################
COPY_FOLDER=$HOME/Bureau
# Dossier de copie
## /!\ À remplacer si besoin
if [[ -d $COPY_FOLDER ]]; then
echo "directory ... ok" > /dev/null
else
notify-send -i error "Copy-Flash" "\nErreur : $COPY_FOLDER introuvable\nCopie dans /tmp"
COPY_FOLDER=/tmp
fi
#Utiliser /tmp comme dossier de copie alternatif si celui indiqué n'existe pas
BROWSER="firefox"
# Nom du navigateur à utiliser
## /!\ À remplacer si besoin
if [[ $BROWSER=firefox || $BROWSER=iceweasel ]]; then
NPROCESS=$(ps aux | grep flash | grep -v "grep" | awk '{print $2}')
# Numéro du processus flash si utilisation de firefox ou iceweasel
else
NPROCESS=$(pgrep $BROWSER)
# /!\ Commande testée et validée pour midori, arora et uzbl-core. Erreur possible pour d'autres navigateurs.
fi
FICHIER=$(cd /proc/$NPROCESS/fd && ls -la | grep Flash | awk '{print $8}' && cd)
# Liste les fichiers vidéos
NBRE_FICHIER=$(echo $FICHIER | wc -w)
# Compte le nombre de fichiers vidéos.
if [ "$NBRE_FICHIER" == "0" ]; then
notify-send -i error "Copy-Flash" "\nErreur : aucune vidéo trouvée"
# Notification d'erreur. Utilisez la ligne suivante en cas de préférence pour les fenêtres zenity
## zenity --info --title="Erreur" --text="Aucune vidéo trouvée."
elif [ "$NBRE_FICHIER" != "1" ]; then
to_print=""
for poet in $FICHIER;
do date=$(stat -Lc '%y' /proc/$NPROCESS/fd/$poet | awk -F \. '{print $1}');
nom=$(stat -c '%N' /proc/$NPROCESS/fd/$poet | awk '{print $3}'| cut -d"/" -f3);
to_print="$to_print \"\" \"$poet\" \"$nom\" \"$date\"";
done;
# Fenêtre zenity de sélection unique (option --radiolist) si plusieurs vidéos en parallèle
video_a_copier=$(echo $to_print | xargs zenity --title='Choix du film à copier' --list --text="" --column=" " --column="N°" --column="Nom" --column="Date" --radiolist --width=500 --height=300 --separator=' ');
renommer=$(stat -c '%N' /proc/$NPROCESS/fd/$video_a_copier | awk '{print $3}'| cut -d"/" -f3)
# Choix de la vidéo à copier
if [ -z "$video_a_copier" ]; then
exit 0;
# Bouton annuler ou aucune vidéo choisie
fi
taille_1=$(stat -Lc '%s' /proc/$NPROCESS/fd/$video_a_copier)
sleep 1
taille_2=$(stat -Lc '%s' /proc/$NPROCESS/fd/$video_a_copier)
while test $taille_1 -ne $taille_2
do
taille_mo=$(($taille_2/10**6))
notify-send -i clock "Copy-Flash" "\nAttente de la fin de mise en cache : $taille_mo Mo" &
taille_1=$(stat -Lc '%s' /proc/$NPROCESS/fd/$video_a_copier)
sleep 10
taille_2=$(stat -Lc '%s' /proc/$NPROCESS/fd/$video_a_copier)
# Attente durant la mise en cache de la vidéo choisie et notifications
if test $taille_1 -eq $taille_2
then
break
fi
done
taille_mo=$(($taille_2/10**6))
cp /proc/$NPROCESS/fd/$video_a_copier $COPY_FOLDER; mv $COPY_FOLDER/$video_a_copier $COPY_FOLDER/$renommer &
notify-send -i folder-download "Copy-Flash" "\nCopie de la vidéo $renommer ($taille_mo Mo) \n$COPY_FOLDER" &
# Copie de la vidéo et notification si la mise en cache est terminée
else
taille_1=$(stat -Lc '%s' /proc/$NPROCESS/fd/$FICHIER)
sleep 1
taille_2=$(stat -Lc '%s' /proc/$NPROCESS/fd/$FICHIER)
while test $taille_1 -ne $taille_2
do
taille_mo=$(($taille_2/10**6))
notify-send -i clock "Copy-Flash" "\nAttente de la fin de mise en cache : $taille_mo Mo" &
taille_1=$(stat -Lc '%s' /proc/$NPROCESS/fd/$FICHIER)
sleep 10
taille_2=$(stat -Lc '%s' /proc/$NPROCESS/fd/$FICHIER)
if test $taille_1 -eq $taille_2
then
break
fi
done
taille_mo=$(($taille_2/10**6))
renommer=$(stat -c '%N' /proc/$NPROCESS/fd/$FICHIER | awk '{print $3}'| cut -d"/" -f3)
cp /proc/$NPROCESS/fd/$FICHIER $COPY_FOLDER; mv $COPY_FOLDER/$FICHIER $COPY_FOLDER/$renommer &
notify-send -i folder-download "Copy-Flash" "\nCopie de la vidéo $renommer ($taille_mo Mo) \n$COPY_FOLDER" &
fi
# Notifications, attente et copie directe si une seule vidéo est présente
exit 0
Et voici les modifications du code pour sélectionner plusieurs fichiers (les points de blocages sont indiqués en commentaires):
#!/bin/bash
#########################################################################################################
# Description: Permet de sauvegarder les videos flash en cours dans le navigateur. #
# Dépendances: grep; zenity; awk; #
# Auteurs: lylambda; bece (amélioration) #
# Version: Copy-Flash 0.5 alpha #
# Licence: gpl #
# http://forum.ubuntu-fr.org/viewtopic.php?id=424080 #
#########################################################################################################
COPY_FOLDER=$HOME/Bureau
# Dossier de copie
## /!\ À remplacer si besoin
if [[ -d $COPY_FOLDER ]]; then
echo "directory ... ok" > /dev/null
else
notify-send -i error "Copy-Flash" "\nErreur : $COPY_FOLDER introuvable\nCopie dans /tmp"
COPY_FOLDER=/tmp
fi
#Utiliser /tmp comme dossier de copie alternatif si celui indiqué n'existe pas
BROWSER="firefox"
# Nom du navigateur à utiliser
## /!\ À remplacer si besoin
if [[ $BROWSER=firefox || $BROWSER=iceweasel ]]; then
NPROCESS=$(ps aux | grep flash | grep -v "grep" | awk '{print $2}')
# Numéro du processus flash si utilisation de firefox ou iceweasel
else
NPROCESS=$(pgrep $BROWSER)
# /!\ Commande testée et validée pour midori, arora et uzbl-core. Erreur possible pour d'autres navigateurs.
fi
FICHIER=$(cd /proc/$NPROCESS/fd && ls -la | grep Flash | awk '{print $8}' && cd)
# Liste les fichiers vidéos
NBRE_FICHIER=$(echo $FICHIER | wc -w)
# Compte le nombre de fichiers vidéos.
if [ "$NBRE_FICHIER" == "0" ]; then
notify-send -i error "Copy-Flash" "\nErreur : aucune vidéo trouvée"
# Notification d'erreur. Utilisez la ligne suivante en cas de préférence pour les fenêtres zenity
## zenity --info --title="Erreur" --text="Aucune vidéo trouvée."
elif [ "$NBRE_FICHIER" != "1" ]; then
to_print=""
for poet in $FICHIER;
do date=$(stat -Lc '%y' /proc/$NPROCESS/fd/$poet | awk -F \. '{print $1}');
nom=$(stat -c '%N' /proc/$NPROCESS/fd/$poet | awk '{print $3}'| cut -d"/" -f3);
to_print="$to_print \"\" \"$poet\" \"$nom\" \"$date\"";
done;
# Fenêtre zenity de sélection multiple (option --checklist) si plusieurs vidéos en parallèle
video_a_copier=$(echo $to_print | xargs zenity --title='Choix du film à copier' --list --text="" --column=" " --column="N°" --column="Nom" --column="Date" --checklist --width=500 --height=300 --separator='\n');
echo "$video_a_copier" > $COPY_FOLDER/recup1;
# "echo" utilisé pour vérifier la sortie en liste
renommer=$(stat -c '%N' /proc/$NPROCESS/fd/$video_a_copier | awk '{print $3}'| cut -d"/" -f3);
# Sélection des vidéos à copier et variable de renommage
echo "$renommer" > $COPY_FOLDER/recup2
# "echo" utilisé pour vérifier le renommage en série
## Problème : seule la première vidéo obtient une variable de renommage
if [ -z "$video_a_copier" ]; then
exit 0;
# Bouton annuler ou aucune vidéo choisie
fi
taille_1=$(stat -Lc '%s' /proc/$NPROCESS/fd/$video_a_copier)
sleep 1
taille_2=$(stat -Lc '%s' /proc/$NPROCESS/fd/$video_a_copier)
while test $taille_1 -ne $taille_2
do
taille_mo=$(($taille_2/10**6))
notify-send -i clock "Copy-Flash" "\nAttente de la fin de mise en cache : $taille_mo Mo" &
taille_1=$(stat -Lc '%s' /proc/$NPROCESS/fd/$video_a_copier)
sleep 10
taille_2=$(stat -Lc '%s' /proc/$NPROCESS/fd/$video_a_copier)
# Attente durant la mise en cache et notifications
if test $taille_1 -eq $taille_2
then
break
fi
done
taille_mo=$(($taille_2/10**6))
cp /proc/$NPROCESS/fd/$video_a_copier $COPY_FOLDER; mv $COPY_FOLDER/$video_a_copier $COPY_FOLDER/$renommer &
notify-send -i folder-download "Copy-Flash" "\nCopie de la vidéo $renommer ($taille_mo Mo) \n$COPY_FOLDER" &
# Copie de la vidéo et notification si la mise en cache est terminée
## Problème : seule la premiere vidéo est copiée
else
taille_1=$(stat -Lc '%s' /proc/$NPROCESS/fd/$FICHIER)
sleep 1
taille_2=$(stat -Lc '%s' /proc/$NPROCESS/fd/$FICHIER)
while test $taille_1 -ne $taille_2
do
taille_mo=$(($taille_2/10**6))
notify-send -i clock "Copy-Flash" "\nAttente de la fin de mise en cache : $taille_mo Mo" &
taille_1=$(stat -Lc '%s' /proc/$NPROCESS/fd/$FICHIER)
sleep 10
taille_2=$(stat -Lc '%s' /proc/$NPROCESS/fd/$FICHIER)
if test $taille_1 -eq $taille_2
then
break
fi
done
taille_mo=$(($taille_2/10**6))
renommer=$(stat -c '%N' /proc/$NPROCESS/fd/$FICHIER | awk '{print $3}'| cut -d"/" -f3)
cp /proc/$NPROCESS/fd/$FICHIER $COPY_FOLDER; mv $COPY_FOLDER/$FICHIER $COPY_FOLDER/$renommer &
notify-send -i folder-download "Copy-Flash" "\nCopie de la vidéo $renommer ($taille_mo Mo) \n$COPY_FOLDER" &
fi
# Notifications, attente et copie directe si une seule vidéo est présente
exit 0
Hors ligne
#2 Le 19/04/2011, à 13:28
- DEoT
Re : Script bash : traiter successivement les éléments d'une sortie
Ça m'a l'air bien compliqué tout ça .
Personnellement j'utilise ce script qui fonctionne bien (même pour plusieurs vidéos).
#!/bin/bash
DEST="/tmp/"
PID=`ps x | grep npviewer.bin | grep -v grep | awk '{print $1}'`
FD=`lsof -p $PID | grep Flash | awk '{print $4}' | sed 's/[a-z]$//'`
while IFS=' ' read -ra ADDR; do
for x in "${ADDR[@]}"; do
# process "$x"
FN=`mktemp --tmpdir="$DEST"` # create a temp file
cp "/proc/$PID/fd/$x" "$FN" # copy video to the temp file
S=`du -h "$FN" | awk '{print $1}'` # get its size
echo "copied video $x to $FN ($S)" # print info
done
done <<< "$FD"
Dans l'état ça ne fonctionne qu'avec firefox (cf ligne 3), mais la modification devrait être simple (tu dois même pouvoir utiliser des morceaux de ton code).
À la base ça vient d'ici.
DEoT
"Les jeux vidéos n'affectent pas les enfants : je veux dire si Pac-Man nous avait influencé étant enfant, nous devrions tous courrir en rond dans des pièces sombres, en gobant des pillules magiques tout en écoutant de la musique répétitive."
Hors ligne
#3 Le 20/04/2011, à 18:00
- lylambda
Re : Script bash : traiter successivement les éléments d'une sortie
Woo, que c'est beau un code clair et compact ! Du coup, j'ai un peu honte du mien ^^
Merci DEoT, de m'avoir fait partager ce script ! Je n'ai plus qu'à le comprendre parfaitement pour épurer le mien (il me falloir un peu de temps ).
Hors ligne
#4 Le 20/04/2011, à 20:36
- twocats
Re : Script bash : traiter successivement les éléments d'une sortie
Encore plus compact :
#!/usr/bin/env bash
DEST="/tmp/"
PID=`ps x | awk '/npviewer.bin/ {print $1}'`
FD=`lsof -p $PID | awk '/Flash/ {print $4}' | sed 's/[a-z]$//'`
while IFS=' ' read -ra ADDR; do
for x in "${ADDR[@]}"; do
# process "$x"
FN=`mktemp --tmpdir="$DEST"` # create a temp file
cp "/proc/$PID/fd/$x" "$FN" # copy video to the temp file
S=`du -h "$FN" | awk '{print $1}'` # get its size
echo "copied video $x to $FN ($S)" # print info
done
done <<< "$FD"
La réponse est 42
Hors ligne
#5 Le 21/04/2011, à 11:48
- lylambda
Re : Script bash : traiter successivement les éléments d'une sortie
Après test, il permet bien de copier toutes les vidéos en même temps. Par contre, pour qu'il fonctionne (aussi bien celui de DEoT que de twocats), j'ai dut remplacer la 3ème ligne par ma commande :
PID=`ps aux | grep flash | grep -v "grep" | awk '{print $2}'`
Vis à vis du mien, il a quelques restrictions :
- Le dossier de destination (/tmp/) n'est pas modifiable, sinon le script ne fonctionne plus.
- Il faut attendre la fin de la mise en cache, sinon on récupère des vidéos incomplètes.
- Comme tu l'as dit DEoT, il ne fonctionne qu'avec firefox et iceweasel. Pour la plupart des autres (midori par exemple), remplacer la 3ème ligne par la suivante devrait le rendre fonctionnel, non ?
PID=`pgrep midori`
Dernière modification par lylambda (Le 21/04/2011, à 11:49)
Hors ligne
#6 Le 29/04/2011, à 16:58
- Xanatos00
Re : Script bash : traiter successivement les éléments d'une sortie
Salut,
le script fonctionne au poil, à défaut de pouvoir changer le dossier /tmp/
j'ai rajouté un petit mv vers un dossier final avant la fin de boucle
combiné à AppLauncher c'est grandement pratique.
pour pousser l'automatisation jusqu'au bout, il faudrait pouvoir :
# ouvrir la vidéo en onglet
# mettre automatiquement celle-ci en pause
# repérer quand celle-ci est complètement en tampon
# lancer le script
# fermer l'onglet de la vidéo
/presque_utopiste
Hors ligne
#7 Le 01/05/2011, à 09:01
- lylambda
Re : Script bash : traiter successivement les éléments d'une sortie
# repérer quand celle-ci est complètement en tampon
# lancer le script
Pour ces deux points, c'est assez facile (cf mon script de copie).
Bon ce n'est peu être pas le plus optimisé, mais je fais une boucle vérifiant régulièrement la taille de la vidéo avant de lancer la copie :
taille_1=$(stat -Lc '%s' /proc/$NPROCESS/fd/$video_a_copier)
sleep 1
taille_2=$(stat -Lc '%s' /proc/$NPROCESS/fd/$video_a_copier)
while test $taille_1 -ne $taille_2
do
taille_mo=$(($taille_2/10**6))
notify-send -i clock "Copy-Flash" "\nAttente de la fin de mise en cache : $taille_mo Mo" &
taille_1=$(stat -Lc '%s' /proc/$NPROCESS/fd/$video_a_copier)
sleep 10
taille_2=$(stat -Lc '%s' /proc/$NPROCESS/fd/$video_a_copier)
# Attente durant la mise en cache et notifications
if test $taille_1 -eq $taille_2
then
break
fi
Hors ligne
#8 Le 03/05/2011, à 15:08
- Xanatos00
Re : Script bash : traiter successivement les éléments d'une sortie
Salut,
effectivement, j'avais omis ceci
sinon pour ceci :
# ouvrir la vidéo en onglet
mozilla -remote "openurl($lien)"
http://www.mozilla.org/unix/remote.html
# mettre automatiquement celle-ci en pause
je cherche
# fermer l'onglet de la vidéo
via le task manager peut être ? firefox sépare ses processus maintenant non ?
Hors ligne