Contenu | Rechercher | Menus

Annonce

L'équipe des administrateurs et modérateurs du forum vous invite à prendre connaissance des nouvelles règles.
En cas de besoin, vous pouvez intervenir dans cette discussion.

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 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 tongue.

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 roll ).

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