# [OFF] Questions script shell (Résolu)

## jerep6

Salut, je souhaite écrire un petit script en bash me permettant de réduire la qualité de mes photos. J'ai la commande suivante : 

```
mogrify -adaptive-resize 2500 -quality 70 photo.JPG
```

Je souhaite appliquer cette commande seulement aux images ayant une certaine dimension. Il faut donc obtenir les dimensions de l'image. J'ai trouvé ceci : 

```
identify "ma photo.JPG"

ma photo.JPG JPEG 2592x1944 2592x1944+0+0 8-bit DirectClass 2.181mb 0.390u 0:02
```

Je ne sais pas comment isoler les dimensions (2592x1944) car leur place dans le retour dépend du nom de l'img (espace ou pas espace).

1. Comment obtenir dans une variable la hauteur / largeur d'une img

2. Comment récupérer dans une variable le type mime d'un fichier ?

Pour le moment je récupère l'extension, mais c'est pas très cool.

Merci.Last edited by jerep6 on Sun Oct 25, 2009 5:21 pm; edited 1 time in total

----------

## freezby

Yop,

```
man identify
```

 devrait t'aider je pense  :Smile: 

EDIT : j'ai rien dit, comme j'ai pas de gentoo pour tester, j'ai pas fait gaffe, je pensais que les options permettaient de sortir spécifiquement les infos mais non  :Sad: 

----------

## jerep6

J'ai regardé (vite fais je dois l'avouer) le man mais je n'ai rien trouvé de pertinent.

La commande se rapprochant le plus est identify -verbose

```
identify -verbose "ma photo.JPG"                

Image: DSC0955 6.JPG                                                     

  Format: JPEG (Joint Photographic Experts Group JFIF format)            

  Class: DirectClass                                                     

  Geometry: 2592x1944+0+0                                                

  Resolution: 72x72

.........
```

Je ne sais tjs pas comment isoler les dimensions.

----------

## kernelsensei

Salut,

est-ce que ça serait un bon point de départ pour toi ? 

```
identify -verbose imgp6975.jpg|grep Geometry|cut -d: -f2
```

ou encore

```
identify -verbose imgp6975.jpg|grep Geometry|awk -F": " '{print $2}'|cut -d+ -f1
```

EDIT : Pour le type mime : file -i tonfichier

----------

## jerep6

Merci, c'est nickel comme point de départ. Par contre, c'est un peu lent (la faute de l'option -verbose).

----------

## freezby

en farfouillant un peu, il y a une autre méthode :

```
identify -format "%h" photo.jpg
```

 renvoie la hauteur de l'image

```
identify -format "%w" photo.jpg
```

 renvoie la largeur de l'image

```
identify -format "%m" photo.jpg
```

 renvoie le mimetype de l'image

----------

## kernelsensei

Bon, en fait apres lecture de la manpage il y a quand même moyen d'éviter tout ce bordel  :Wink: 

```
identify -format "%wx%h" monfichier.jpg
```

EDIT : Ah, grillé ^^

----------

## jerep6

Vous êtes géniaux. Merci beaucoup.

Une question : pourquoi dans cette commande tu utilises awk et cut alors que l'ont peut faire tous avec awk ?

```
identify -verbose imgp6975.jpg|grep Geometry|awk -F": " '{print $2}'|cut -d+ -f1

identify -verbose imgp6975.jpg|grep Geometry|awk -F": " '{print $2}'|awk -F"+" '{print $1}'
```

Cut présente il un avantage ?

Merci encore.

EDIT : Comment avez vous trouvé les paramètres de l'option format ? Mon man ne les indique pas.

-format "string"     output formatted image characteristics

----------

## freezby

Perso, pour la hauteur et la largeur, en voyant des script sur google. Pour le type mime, en testant des lettres :p

----------

## Magic Banana

Vous aimez compliquer les choses !  :Razz: 

```
height=`identify -format "%h" "$picture"`

width=`identify -format "%w" "$picture"`

compression=`identify -format "%C" "$picture"`
```

Tu as ainsi les trois informations que tu souhaites dans trois variables.

----------

## freezby

Vi, c'est qu'on a indiqué par la suite :p

tiens et pour ta question sur les paramètres jerep, je viens de trouver ça : http://www.imagemagick.org/script/escape.php  :Wink: 

----------

## jerep6

Merci à tous.

Maintenant ya plus ka !

----------

## kernelsensei

pour cut vs. awk, c'est juste que j'avais édité mon message plusieurs fois, au debut yavait cut partout et aussi sed dans un certain cas. Après édition j'ai opté pour une commande avec un séparateur de 2 caractères et pas de sed. cut n'accepte pas les séparateurs de plus d'un caractère, mais awk si, du coup je suis passé à awk pour la commande avec le séparateur de 2 caractères.

----------

## xaviermiller

 *Magic Banana wrote:*   

> Vous aimez compliquer les choses ! 
> 
> ```
> height=`identify -format "%h" "$picture"`
> 
> ...

 

Pas mal, mais tu auras 3 traitements identiques par fichier.

----------

## Bapt

juste pourquoi pas un simple : 

```
eval `identify -format "height=%h\nwidth=%w\ncompression=%C" monfichier.jpg`
```

Un seul appel système, pas de pipe et de truc tordus massacreurs de chatons etc.

PS: les | grep | awk vous pouvez les virer avec awk '/regex/ { print bla }' ça sauvera un chaton[/code]

----------

## Magic Banana

 *XavierMiller wrote:*   

>  *Magic Banana wrote:*   Vous aimez compliquer les choses ! 
> 
> ```
> height=`identify -format "%h" "$picture"`
> 
> ...

 

Vrai. Bapt a probablement trouvé la façon la plus propre de faire les choses. Une autre façon est d'affecter les paramètres de position :

```
set `identify -format "%h %w %C" "$picture"`
```

Il n'y a probablement pas plus court... mais c'est un peu casse gueule d'utiliser les paramètres de position à tout va.Last edited by Magic Banana on Mon Oct 26, 2009 12:30 pm; edited 1 time in total

----------

## xaviermiller

Vive le travail d'équipe  :Smile: 

----------

## jerep6

Voilà, j'ai terminé le script.

Je ne connais pas bien la programmation shell donc si vous pouvez critiquer mon script j'en serai ravi.

N'hésitez pas !!! 

Par exemple : Le parsage des arguments se fait il comme ça ?

```
#!/bin/bash

# Réduit la qualité des photos pour gagner de la place sur le disque dur

# et réoriente les photos (options -auto-orient de mogrify)

# La qualité sera réduite uniquement dans le cas où la qualité de la photo

# et supérieure à la qualité voulue

##################################################################

#         FONCTIONS

##################################################################

#Affiche les options disponibles

aide() {

   echo "$0 [options] dossiers"

   echo "-h   affiche ce message"

   echo "-R   traitement récursif des dossiers"

}

#Traite un dossier passé en paramètre

traiter_dossier() {

   for fichier in "$1/"*

      do

      #Si dossier ET que option recursif 

      if [ -d "$fichier" ] && [ $recursif -eq 1 ]; then

         traiter_dossier "$fichier"

      else

         #Type mime du fichier pour tester si c'est une img

         mime=`file -i "$fichier" | awk -F ": " '{print $2}'`

         if [ "$mime" = "image/jpeg" ]; then

            #Qualité et dimensions de l'img

            eval `identify -format "qualite=%Q\ndimensions=%wx%h" "$fichier"`

            #Si qualite > qualite_min (img de qualité suffisante, on peut reduire sa qualité)

            if [ $qualite -gt $qualite_min ]; then

               echo "$fichier ..."

               mogrify -auto-orient -quality $qualite_min -adaptive-resize $dimensions "$fichier"

            fi

         fi

      fi

   done   

}

qualite_min="80"   #Qualité des photos (les img ayant une qualité < ne seront pas touchées)

recursif=0      #1 = parcours récursif des dossiers

##### Recup arguments ######

index=0;

while [ -n "$1" ]; do

   case $1 in

      -h) aide

         exit 0

         ;;

      -R)   recursif=1

         ;;

      -q) qualite_min=$2

         shift

         ;;

      *)   

         #Si dossier existe alors ajout au tableau des dossiers à traiter

         if [ -d "$1" ]; then

            dossiers[$index]="$1"

            index=$(( $index + 1 ))

         fi

         ;;

   esac

   shift

done

#Si aucun dossier en param => dossier courant

if [ ${#dossiers[*]} -eq 0 ] ; then

  dossiers[0]="$PWD"

fi

#Message d'avertissement. L'utilisateur doit donner son accord pour continuer

echo -n "Attention, les images originales seront altérées. Continuer [o/n] ?"

read reponse

if [ $reponse = "n" ]; then

   exit 0

fi

#Pour chaque dossier => parcours des fichiers

for unDossier in "${dossiers[@]}"; do

   traiter_dossier "$unDossier"

done;
```

----------

## Magic Banana

Voilà ce que j'aurais fait :

```
#!/bin/bash

# Réduit la qualité des photos pour gagner de la place sur le disque dur

# et réoriente les photos (options -auto-orient de mogrify)

# La qualité sera réduite uniquement dans le cas où la qualité de la photo

# et supérieure à la qualité voulue

##################################################################

#         FONCTIONS

##################################################################

# Inutile mettre une commande seule (et appelée à un seul endroit) dans une fonction

#Traite un fichier passé en paramètre

traiter() {

   if [ -d "$1" ]; then

      if [ -n "$recursif" ]; then

    for fichier in "$1"/*

    do

       traiter "$fichier"

    done

      else

          # Un répertoire mais l'utilisateur n'a pas mis -R: message d'erreur et aucun traitement

     echo "\"$1\" est un répertoire et -R n'a pas été choisi" >&2

      fi

   else

      #Type mime, qualité et dimensions de l'img (pas de awk inutile et coûteux en temp)

      eval `identify -format "mime=%C\nqualite=%Q\ndimensions=%wx%h" "$1"`

      # Pourquoi deux tests if quand on peut faire une conjonction avec -a ?

      if [ "$mime" = "JPEG" -a $qualite -gt $qualite_min ]; then

         #Si qualite > qualite_min (img de qualité suffisante, on peut reduire sa qualité)

          echo "$1 ..."

          mogrify -auto-orient -quality $qualite_min -adaptive-resize $dimensions "$1"

      fi

   fi

}

qualite_min="80"   #Qualité des photos (les img ayant une qualité < ne seront pas touchées)

# La seule présence de quelque chose dans recursif indique que l'utilisateur à choisi cette option

##### Recup arguments ######

# Pas la peine de mettre un ';' en fin de ligne

index=0

while [ -n "$1" ]; do

   case $1 in

      -h) #Affiche les options disponibles

           # un echo peut afficher plusieurs lignes

         echo "$0 [options] dossiers

-h   affiche ce message

-R   traitement récursif des dossiers"

         # Par défaut exit renvoi le succès de la dernière commande

         exit

         ;;

      -R)   recursif=1

         ;;

      -q) qualite_min=$2

         shift

         ;;

      *)   

         #Si fichier existe (l'utilisateur peut directement passer une photo en paramètre) alors ajout au tableau des fichiers à traiter

         if [ -e "$1" ]; then

            fichiers[$index]="$1"

       # J'aime pas le double parenthèsage

            let "index += 1"

         fi

   esac

   shift

done

# Trop dangereux le paramètre * par défaut

#Message d'avertissement. L'utilisateur doit donner son accord pour continuer

# Il est plus sûr de choisir "non" comme réponse par défaut !

# L'option -n1 pour un seul caractère et -p pour le prompt... et une espace après le '?' pour faire beau

read -n1 -p "Attention, les images originales seront altérées. Continuer [o/N] ? " reponse

# Un saut de ligne (toujours pour faire beau)

echo

# Les guillemets autour de $reponse évitent une erreur si l'utilisateur appuie sur entrée sans avoir entré de lettre

if [ "$reponse" = "o" ]; then

#Pour chaque dossier => parcours des fichiers

   for unFichier in "${fichiers[@]}"; do

      traiter "$unFichier"

      # Encore un inutile ';' en fin de ligne

   done

fi
```

Les commentaires détaillent les modifications (possibilité de passer directement des images, confirmation en une touche, etc.). Si tu veux un meilleur traitement des options, tu peux te pencher sur getopt (ou sur getopts qui est une commande "builtin" de Bash).

----------

## jerep6

Merci pour ces corrections.

 *Quote:*   

> # Pourquoi deux tests if quand on peut faire une conjonction avec -a ? 

 

&& et -a n'ont pas le même comportement

expression1 && expression2 : si expression1 est fausse alors expression2 ne sera pas évaluée

expression1 -a expression2 : même si expression1 et fausse, expression2 sera évaluée

----------

## Magic Banana

Effectivement. log contient "Magic Banana" lorsque le script suivant est exécuté :

```
#!/bin/bash

magic ()

{

    echo -n "Magic" > log

    echo 0

}

banana ()

{

    echo " Banana" >> log

    echo 0

}

if [ `magic` = 1 -a `banana` = 0 ]

then

    echo WTF

else

    echo OK

fi
```

Du coup, c'est toi qui me fais découvrir des choses !  :Very Happy: 

----------

