IPB

Bienvenue invité ( Connexion | Inscription )

2 Pages V  < 1 2  
Reply to this topicStart new topic
> Modifier une donnée EXIF en applescript, La valeur à écrire est à lire dans un fichier excel
Options
Jaypee
posté 2 Nov 2016, 13:02
Message #31


Macbidouilleur d'Or !
*****

Groupe : Membres
Messages : 2 486
Inscrit : 29 Aug 2002
Membre no 3 340



@PBell
Il faut raisonner "Inversion de controle" ou "méthode Hollywood" ou "Ne nous appelez pas, NOUS vous appelerons".
Ce n'est pas au script de trouver où chercher il faut lui apporter comme argument (c-à-d $1, puisque $0 est le nom du script lui-même) donc $1 est un nom de la form G_*.jpg

Et ce script travaille sur ce seul fichier mais fait bien le boulot de A à Z.
- extrait le produit du nom
- recherche les dimensions dans la base SQLite3
- ecrit les exifs
- ecrit une trace à la console pour qu'on puisse suivre la progression du travail.

Pas de boucle for, un seul fichier est traité

Appelons ce script dims2exif.sh qui devra avoir le mode 755 (ou +x) c-à-d éxécutable


Puis de l'extérieur un autre script s'occupe de fournir les noms individuellement:
- Voir juste pour la compréhension la sortie de:
find /racine -name "G_*jpg" # normalement il faudrait ajouter -print, mais c'est implicite.
ça trouve récursivement tous les fihciers jpg sous la racine

Pour ce deuxième script, appelons le dossier2exif.sh et qui prend "/racine" en entrée (donc $1=/racine) et le motif "G_*jpg" comme $2
find $1 -name $2 -exec dims2exif.sh {} \; # <--- les {} représente une ligne de la réponse

Il faut suivre les bonnes pratiques habituelles, afficher l'aide si on envoie la commande sans rien. $# sert à compter les arguments donc si $# < 2 afficher l'aide sinon commencer le traitement.
Il faut valider les entrées $1 existe-t-il ? $1 se termine-t-il avec {jpg|gif|png..}

Idem pour les deux scripts.

On peut commencer simple:
dims2exif.sh ne contient que: ls -l $1 # lister le fichier donné.

Puis on travaille le dossier2exif.sh. On doit voir la sortie du ls -l uniquement pour les fichiers du motif. Quand tout celà est OK, on s'attaque à dims2exif.sh, facile à tester pour un seul fichier.
- Indice pour le parsing du nom -> produit: echo $1 | awk -F _ '{echo $2}' devrait faire le boulot.

C'est juste des directions générales.
J-P
PS: Sur les pipes. Les pipes sont les emblèmes de la programmation du style "fonctionnel". L'idée c'est que la liste devant le pipe, doit être transformée par une fonction pour fournir une liste de même taille. En programmation fonctionnelle, c'est un map: en gros f(liste) = liste des f(x), pour tout x appartenant à la liste. Parfois, une liste donne une seule valeur, genre une liste de nombres done une valeur unique, la somme ou le produit de tous les nombres. C'est ce qu'on appelle un réduce. Map et Reduce sont les deux mamelles de ce style de programamtion.

Pour pouvoir utiliser une liste de noms de fichier il faut souvent faire un: ls -C1: listing sur une colonne, mais un foreach est ensuite indispensable. Je préfère le pattern "Visiteur" de la commande find.

Ce message a été modifié par Jaypee - 2 Nov 2016, 13:12.
Go to the top of the page
 
+Quote Post
Jaypee
posté 2 Nov 2016, 13:17
Message #32


Macbidouilleur d'Or !
*****

Groupe : Membres
Messages : 2 486
Inscrit : 29 Aug 2002
Membre no 3 340



@yponomeute @PBell

Une fois qu'on a le script shell qui fait bien tout avec juste la racine et le motif des images, là on peut utiliser AppleScript pour faire un truc sympa pour la saisie des données.

Si je me rapelle bien, avec XCode + AppleScript on peut faire un vrai dialogue modal macOS, avec toutes les questions en même temps dans un formulaire et les boutons qui vont bien.

J-P

Go to the top of the page
 
+Quote Post
PBell
posté 2 Nov 2016, 19:53
Message #33


Macbidouilleur de bronze !
**

Groupe : Membres
Messages : 264
Inscrit : 7 Dec 2013
Lieu : Ile de France
Membre no 188 169



Bonsoir Jaypee,
Merci de ton aide...j'ai encore besoin de ton guidage.
J'ai bien compris l'utilisation d'un script de boucle et d'un autre de sub routine qui traite le fichier un par un dans la boucle.
Cependant, je me suis exercé et j'ai un problème avec la boucle.

Commençons par ce qui fonctionne :
Au début de mon script, je teste pour l'instant que l'utilisateur entre bien 2 paramètres: le dossier et le fichier produit/dimension
CODE
#!/bin/bash
# test des paramètres d’entrée
if [ $# != 2 ]
then
echo ‘Erreur: il faut 2 paramètres, le dossier et le fichier des dimensions’
exit
fi

Je peux ainsi utiliser, comme tu l'indiques, les variable $1 (le dossier) et $2 le fichier produit/dimensions

Pour le traitement du fichier, extraction du nom du produit ici pour le fichier G_121200_125200/G_121202_21_ZP_1_test.jpg et recherche/extraction des dimensions dans le fichier WF30000.txt.
Là aussi, tout va bien: Je définie d'abord la variable produit, puis j'utilise cette variable pour obtenir la variable dim qui contient la colonne 2 :
CODE
produit=$(basename /Users/imac27/Desktop/G_121200_125200/G_121202_21_ZP_1_test.jpg | cut -c3-8)
pdim=$(grep $produit /Users/imac27/Desktop/WF30000.txt | cut -c8-100)

la variable pdim renvoie les dimensions qui seront utilisables dans l'exif.
Je n'ai pas de souci sur la partie exif pour l'instant.


Là où je bloque c'est sur la boucle. J'ai bien un find qui fonctionne en mode terminal direct, et me donne la liste des fichiers voulus:
CODE
find  /dossier -name  "G_*.jpg“

Mais dans mon shell script, si je fais un find $1 -name "G_*.jpg", j'ai une erreur sur le directory.
-idem en changeant les " par des '
-idem si je remplace directement le $1 par le dossier en litéral.

J'ai essayé de définir une variable Liste à partir de find pour faire une boucle for...sans succès !!
CODE
Liste= find mon_dossier -name 'G_$.jpg'
for fichier in Liste
do
echo 'voici mon fichier=' fichier
done

Cela ne marche pas. Je ne comprends pas mon erreur. J'ai essayé une autre boucle qui, elle, fonctionne :
CODE
for fichier in /Users/imac27/Desktop/Traitement_images/Masstest/Petit/*
do
echo ‘fichier trouve=‘ $(basename $fichier)
done


Help !!
Merci d'avance


--------------------
iiMac 24 M1 16Go/1To 13.5.1
iMac 27 i5 3,1GHz 8Go/1To 10.11.6 / 10.6.8
iMac 20 C.Duo 2,6Ghz 8Go/350Go 10.6.8 / 10.11
Mini C.Duo 2,0Ghz 2Go/500Go 10.6.8
Go to the top of the page
 
+Quote Post
Jaypee
posté 2 Nov 2016, 21:52
Message #34


Macbidouilleur d'Or !
*****

Groupe : Membres
Messages : 2 486
Inscrit : 29 Aug 2002
Membre no 3 340



@PBell, oublie la boucle, et penche-toi sur la commande find. Ensuite, pareil, oublie les greps et les pipes compliqués... C'est chic, mais si ce script plante, tu ne seras pas là pour le réparer. Autant utiliser la technologie la plus efficace qui existe et faire le moins de code possible.
Un proverbe de programmeur: La ligne de code qui ne plantera jamais, c'est celle qu'on aura évité d'écrire.

Pour la démo, je vais générer une nouvelle base compatible avec les codes produits de 2 à 5 caractères, sans formatage par des zéros.
Code
[jaypee:~/workspaces/Ruby]$ irb
irb(main):001:0> File.open '/Users/jaypee/workspaces/Ruby/bdproduits.csv', 'w' do |f| (11..32000).each  {|i| f.write "#{i.to_s},#{10*(1 + i % 5)}x#{20 * (1 + i % 3)}x#{5 * (1 + i % 2)}\n"} end


Puis la base elle même:
Code
[jaypee:~/workspaces/Ruby]$ sqlite3 produits.db
SQLite version 3.14.0 2016-07-26 15:17:14
Enter ".help" for usage hints.
sqlite> create table produits(code, dimensions);
sqlite> .mode csv
sqlite> .import /Users/jaypee/workspaces/Ruby/bdproduits.csv produits
sqlite> .exit


Voici un début de script dims2exif.sh
Code
#!/bin/sh
if [ $# -lt 1 ]; then
    echo Usage: $0 chemin/vers/image.jpg
    exit 0
fi
prod=`echo $1 | awk -F _ '{print $2}'`
echo $prod
dims=`sqlite3 ./produits.db "select dimensions from produits where code = '$prod'"`
echo $dims


Et un exemple d'exécution:
Code
[jaypee:~/workspaces/Ruby]$ ./dims2exif.sh G_12345_320_ZP_1_565656.jpg                      
12345
10x20x10


Pour finir, je fabrique de faux fichiers de taille nulle avec la commande touch dans un dossier pictures:
Code
[jaypee:~/workspaces/Ruby]$ mkdir pictures
[jaypee:~/workspaces/Ruby]$ irb
irb(main):001:0> ile.open '/Users/jaypee/workspaces/Ruby/fakeimg.sh', 'w' do |f| (11..32).each { |i| (11..12).each { |j| f.write "touch pictures/G_#{i.to_s}_#{j.to_s}_ZF_1_XYZ.jpg\n" } } end


On a créé un script fakeimg.sh qui va les créer:
Code
[jaypee:~/workspaces/Ruby]$ chmod +x ./fakeimg.sh
[jaypee:~/workspaces/Ruby]$ ./fakeimg.sh
[jaypee:~/workspaces/Ruby]$ ls -l pictures
total 0
-rw-r--r--  1 jaypee  staff  0  2 nov 22:24 G_11_11_ZF_1_XYZ.jpg
-rw-r--r--  1 jaypee  staff  0  2 nov 22:24 G_11_12_ZF_1_XYZ.jpg
-rw-r--r--  1 jaypee  staff  0  2 nov 22:24 G_12_11_ZF_1_XYZ.jpg
-rw-r--r--  1 jaypee  staff  0  2 nov 22:24 G_12_12_ZF_1_XYZ.jpg
-rw-r--r--  1 jaypee  staff  0  2 nov 22:24 G_13_11_ZF_1_XYZ.jpg
-rw-r--r--  1 jaypee  staff  0  2 nov 22:24 G_13_12_ZF_1_XYZ.jpg
-rw-r--r--  1 jaypee  staff  0  2 nov 22:24 G_14_11_ZF_1_XYZ.jpg
...


Enfin, on utilise la commande find
Code
[jaypee:~/workspaces/Ruby]$ find pictures -name "*jpg" -exec /users/jaypee/workspaces/Ruby/dims2exif.sh {} \;
11
20x60x10
11
20x60x10
12
30x20x5
12
30x20x5
...


La fin finale ? Pas encore. Un exemple de projet Xcode/Cocoa avec de l'AppleScript comme moteur:
http://stackoverflow.com/questions/3483497...cript-and-a-gui l'article contient un lien sur un zip d'exemple

Les deux seuls fichiers à modifier:
- MainMenu.xib pour l' interface utilisateur
- AppDelegate.applescript pour le code
Le reste est fourni et à utiliser tel quel.

J-P

Ce message a été modifié par Jaypee - 2 Nov 2016, 22:59.
Go to the top of the page
 
+Quote Post
teddy7545
posté 3 Nov 2016, 03:57
Message #35


Macbidouilleur de vermeil !
****

Groupe : Membres
Messages : 879
Inscrit : 4 Apr 2004
Lieu : Lorraine - 54
Membre no 17 184



Speed Moock

Le problème de fond et les discussions engagées sont très intéressantes et j'y regarderais d'un peu plus près quand je serais de retour de déplacement ou je suis actuellement.
Personnellement c'est vrai que je me serais davantage tourné vers un shell script pur voir un code ObjC.
Au pire il est assez simple de faire un interface ASOC (applescript objectiveC) et d'appeler un shell ou tout autre code plus performant que AS.
Dans tous les cas si la réécriture de tous les fichiers est nécessaire , le traitement de centaines de fichiers prendra toujours un certain temps dépendant du support sur lequel les fichiers se trouvent.
Les pistes d'optimisations déjà amorcées sont en tous les cas nécessaires et fort intéressantes.
Dans l'attente de regarder cela de plus près, je répond aux problèmes que tu as rencontré dans l'usage du script Shell.

Citation
Là où je bloque c'est sur la boucle. J'ai bien un find qui fonctionne en mode terminal direct, et me donne la liste des fichiers voulus:
Code
find  /dossier -name  "G_*.jpg“


Mais dans mon shell script, si je fais un find $1 -name "G_*.jpg", j'ai une erreur sur le directory.
-idem en changeant les " par des '
-idem si je remplace directement le $1 par le dossier en litéral.

J'ai essayé de définir une variable Liste à partir de find pour faire une boucle for...sans succès !!
Code
Liste= find mon_dossier -name 'G_$.jpg'
for fichier in Liste
do
echo 'voici mon fichier=' fichier
done

Cela ne marche pas. Je ne comprends pas mon erreur.

Pour le problème de find c'est manifestement /dossier qui pose problème et sans doute pas la suite.
Il faut donc vérifier si tu entre un chemin relatif ou non (si tu utilises un chemin relatif tu dois alors tenir compte de l'endroit ou se trouve le script)
Pour éviter les erreurs et les problèmes, il est plus simple d'entrer un chemin complet partant de la racine comme argument
Pas de raison que ça ne fonctionne pas (je suppose qu'il n'y a pas d'espace dans ton chemin sinon quelques précautions supplémentaires sont à prévoir).
Au besoin indiques nous quel chemin tu utilises précisément comme argument, ou as tu stocké ton script et éventuellement depuis quel répertoire tu le lance.

Ensuite pour définir une variable tu dois faire :
Code
Liste=$(find "$1" -name 'G_*.jpg')
Pour avoir la liste entière (dans cette version tu peux utiliser les ' ou les " indifféremment

ou
Code
Liste=$(find "$1" -name "G_$2*.jpg")
Si tu veux n'effectuer la tache que sur le fichier défini dans ta variable $2 (attention la substitution exige alors l'usage des " )

Pour l'utilisation de ta boucle, tu as fais plusieurs erreurs sur l'usage de tes variables.
Si tu défini la variable Liste .... tu devras alors utiliser $Liste pour l'appeler (idem avec fichier qui s'appelle avec $fichier)

Ci-dessous un petit exemple qui fonctionne chez moi et basé sur le début de code que tu avais proposé:
Code
#!/bin/bash
# test des paramètres d’entrée
if [ $# != 2 ]
then
echo ‘Erreur: il faut 2 paramètres, le dossier et le fichier des dimensions’
exit
fi

Liste=$(find "$1" -name "G_*.jpg")
for fichier in "$Liste"
do
echo 'voici mon fichier=' "$fichier"
done
exit


Bon courage

Ce message a été modifié par teddy7545 - 3 Nov 2016, 04:13.


--------------------
MP Intel Dual Xéon 3 GHz - MacOSX 10.10.3 - ATI Radeon HD 5770 - ATTO UL5D - Apple Cinema HD Display 23 pouces
MBP 15' 2017 - MBP 13' mid 2009 - iMac 24' 8,1 2,8GHz - MP G4 MDD Bi 1,25 GHz - MP G4 Quicksylver 933MHz
Go to the top of the page
 
+Quote Post
Speed Moock
posté 3 Nov 2016, 07:38
Message #36


Adepte de Macbidouille
*

Groupe : Membres
Messages : 42
Inscrit : 30 Aug 2016
Membre no 199 619



Bonjour TEddy7545

Le sujet m'échappe complètement et je laisse Jaypee et PBell faire avancer leurs recherches. C'est ce que je trouve magique avec ce forum et l'informatique de passionnés, un sujet a priori simple révèle énormément de subtilités.
Pour ma part je suis sur la version 100% applescript qui tourne lentement mais au moins j'en comprends le moteur.
Les échanges restent toutefois intéressants !

Merci à tous,
Go to the top of the page
 
+Quote Post
Jaypee
posté 3 Nov 2016, 11:47
Message #37


Macbidouilleur d'Or !
*****

Groupe : Membres
Messages : 2 486
Inscrit : 29 Aug 2002
Membre no 3 340



Speed Moock,

J'entends ton souhait.

Je vais faire un dernier test de perf en quasiment vrai grandeur, je vais utiliser de faux fichier jpg, juste pour leur nom, et utiliser une vrai image sacrifice dans la quelle je vais réellement réécrire les EXIF data. Ainsi toutes les vraies opérations sont simulées.

Le choix entre tout comprendre et avoir une solution utilisable sera facile à faire. Ce sera du genre plusieurs heures d'attente contre quelques minutes pour traiter un dossier complet.

Cela n'empêche pas que la solution restera lisible et facilement modifiable.

Je me rends compte de "corner cases":
- A quoi sert l'index avant l'Id unique de la fin du nom?
- Que faire si on a plusieurs index pour le même code produit, on utilise les mêmes dimensions pour tous les index ?

J-P

Ce message a été modifié par Jaypee - 3 Nov 2016, 11:48.
Go to the top of the page
 
+Quote Post
Speed Moock
posté 3 Nov 2016, 13:36
Message #38


Adepte de Macbidouille
*

Groupe : Membres
Messages : 42
Inscrit : 30 Aug 2016
Membre no 199 619



Bonjour Jaypee,
- l'index est un identifiant unique généré par notre outil de shooting afin de garantir l'unicité des images, même si un produit revient en shooting plusieurs semaines après (un produit est défini par le couple code produit & code couleur.)
- il peut y avoir dans le listing excel des doublons de code produit mais ils auront toujours la même taille Exif à rajouter. Du coup le script peut s'arrêter au premier trouvé.

A terme je devrai faire évoluer le script pour écrire plusieurs EXIF renseignées dans les autres colonnes (C, D et E). J'essaierai d'être malin et de bien comprendre le code.

Quoiqu'il en soit merci encore
Go to the top of the page
 
+Quote Post
PBell
posté 3 Nov 2016, 19:09
Message #39


Macbidouilleur de bronze !
**

Groupe : Membres
Messages : 264
Inscrit : 7 Dec 2013
Lieu : Ile de France
Membre no 188 169



Bonsoir Teddy7545,
Grâce à tes conseils, je crois que je progresse un peu.

Mon script est presque complet : il prends tous les fichiers des sous dossier, pour chacun, il extrait le code produit, puis recherche, dans la base, ce code et extrait la colonne 2 contenant les dimensions.
J'ai ajouté un test au cas où il ne trouve pas de dimensions (code produit inexistant dans la base): dans ce cas , pas d'exif.

Enfin, dans le cas où des dimensions sont trouvées, je peux faire l'exiftool.

CODE
#!/bin/bash
# une fois ce texte script enregistré en .sh, faire un chmod +x xxx.sh pour le rendre exécutable
# test des paramètres d’entrée
if [ $# != 2 ]
then
echo ‘Erreur: il faut 2 paramètres, le dossier et le fichier des dimensions’
exit
fi

Liste=$(find "$1" -name "G_*.jpg") #liste les fichiers dans les dossiers et sous dossiers

for fichier in $Liste
do
produit=$(basename $fichier  | cut -c3-8) # pour chaque fichier, extrait le produit = caractères 3 à 8 du nom
pdim=$(grep $produit $2 | cut -c12-100) # cherche via le produit, les dimensions à partir du car 8 (après 6 car de produit et 1 tab)

if [ -z $pdim ]
then
echo “Pas de dimension pour “ $produit
else
echo ‘dim=‘  ‘“$pdim“’
echo ’fichier=‘ $fichier
/usr/local/bin/exiftool -ImageDescription=“test N2“ -Overwrite_Original $fichier
fi
done
echo ‘fin de script’
exit


Comme tu le vois, j'ai remplacé dans cette version la variable pdim (qui doit contenir les dimensions) par "test N2" donc avec un espace...et c'est là mon problème.
C'était, je l'ai compris avec ton post précédent, déjà mon problème de boucle dans un de mes sous dossier avec des espaces dans le nom.
Si le contenu de la variable ne contient pas d'espace, tout va bien et le script fonctionne entièrement.
Si le contenu de la variable contient des espaces, le shell interprète ces espaces comme des séparateurs...d'où les erreurs.

J'ai encore des doutes sur l'utilisation des " et des ' , mais je n'arrive pas à maîtriser les cas où une variable (nom de fichier ou ces dimensions) contient des espaces.
Comment demander au Shell de ne pas les interpréter ? Comment forcer l'utilisation des variables avec des ' (comme en AS)?

J'ai besoin de lumière. Merci d'avance.


--------------------
iiMac 24 M1 16Go/1To 13.5.1
iMac 27 i5 3,1GHz 8Go/1To 10.11.6 / 10.6.8
iMac 20 C.Duo 2,6Ghz 8Go/350Go 10.6.8 / 10.11
Mini C.Duo 2,0Ghz 2Go/500Go 10.6.8
Go to the top of the page
 
+Quote Post
Speed Moock
posté 3 Nov 2016, 21:09
Message #40


Adepte de Macbidouille
*

Groupe : Membres
Messages : 42
Inscrit : 30 Aug 2016
Membre no 199 619



Bonsoir,

Une question sur la commande do shell script :
comment y implanter plusieurs instruction successives similaires ?
exemple :
do shell script "/usr/local/bin/exiftool -Title='" & DimText4 & "' -Overwrite_Original " & quoted form of (UnixPath)
do shell script "/usr/local/bin/exiftool -City='" & DimText5 & "' -Overwrite_Original " & quoted form of (UnixPath)
que je voudrai regrouper sous une unique do shell script
do shell script "/usr/local/bin/exiftool -Title='" & DimText4 & "'; "/usr/local/bin/exiftool -City='" & DimText5 -Overwrite_Original " & quoted form of (UnixPath)

merci
& "' -Overwrite_Original " & quoted form of (UnixPath)
Go to the top of the page
 
+Quote Post
PBell
posté 3 Nov 2016, 21:37
Message #41


Macbidouilleur de bronze !
**

Groupe : Membres
Messages : 264
Inscrit : 7 Dec 2013
Lieu : Ile de France
Membre no 188 169



Bonsoir SpeedMoock,
Il faut mettre tous les champs à modifier à la suite avec des espaces entre :
CODE
/usr/local/bin/exiftool -ImageDescription=‘testPC’ -City='testCity' -Title='Mon_titre' -Overwrite_Original Unixpath


Ce qui donne, en appelant via Applescript pour Title et City:
CODE
do shell script "/usr/local/bin/exiftool -Title='" & DimText4 & "' -City='" & DimText5 -Overwrite_Original " & quoted form of (UnixPath)

(ne pas oublier les espace entre les champs)

Cordialement

Ce message a été modifié par PBell - 3 Nov 2016, 21:37.


--------------------
iiMac 24 M1 16Go/1To 13.5.1
iMac 27 i5 3,1GHz 8Go/1To 10.11.6 / 10.6.8
iMac 20 C.Duo 2,6Ghz 8Go/350Go 10.6.8 / 10.11
Mini C.Duo 2,0Ghz 2Go/500Go 10.6.8
Go to the top of the page
 
+Quote Post
Jaypee
posté 3 Nov 2016, 21:46
Message #42


Macbidouilleur d'Or !
*****

Groupe : Membres
Messages : 2 486
Inscrit : 29 Aug 2002
Membre no 3 340



Je suis en train de faire un timing grandeur nature je m'attends à plus d'une heure de traitement pour 32000 images. J'ai fait 32000 copies d'un petit jpeg de 16K avec les noms qui vont bien. il faut compter 1/3 à 1/2 seconde par image, soit entre 10000 et 16000 secondes en tout.

@PBell regarde la commande tr (fais un man tr dans le Terminal)
Code
[jaypee:~]$ x=`echo "A B CD E F" | tr " " "_"`
[jaypee:~]$ echo $x
A_B_CD_E_F

Merci pour la syntaxe de commande exiftool

Voici mon script final
Code
#!/bin/sh
###############
# Script: dims2exif.sh
###############
if [ $# -lt 1 ]; then
    echo Usage: $0 chemin/vers/image.jpg
    exit 0
fi
fichier=`basename $1`
prod=`echo $fichier | awk -F _ '{print $2}'`
dims=`sqlite3 ./produits.db "select dimensions from produits where code = '$prod'"`
exiftool -ImageDescription=$dims  -Overwrite_Original $1 > /dev/null
echo $1


Et la commande pour l'utiliser:
Code
find pictures/ -name "*jpg" -exec /users/jaypee/workspaces/Ruby/dims2exif.sh {} \;


Un des fichiers modifié:
Code
[jaypee:~/workspaces/Ruby]$ exiftool -exif:ImageDescription pictures/G_14490_12_ZF_1_XYZ.jpg
Image Description               : 10x20x5

J-P

Ce message a été modifié par Jaypee - 3 Nov 2016, 22:40.
Go to the top of the page
 
+Quote Post
teddy7545
posté 4 Nov 2016, 02:49
Message #43


Macbidouilleur de vermeil !
****

Groupe : Membres
Messages : 879
Inscrit : 4 Apr 2004
Lieu : Lorraine - 54
Membre no 17 184



Bonsoir,

Désolé Speed Moock, j'avais en effet lu un peu trop vite les messages.
Mon message précédant s'adressait effectivement davantage aux questions de PBelle qu'à celles de Speed Moock (même si l'objectif final commun est de pouvoir contribuer à solutionner son problème).

Même si Jaypee a avancé de son côté en proposant de nouvelles évolutions de son script, je répond ici pour les problèmes rencontrés par PBelle dans son dernier script avec la boucle.

@PBell
Attention à ne pas confondre ‘ avec ' ou encore “ avec "
En effet, en shell ces caractères ne se comportent pas de la même façon.

Dans tes exemples, les quotes utilisés ne sont pas toujours les bons...ce qui explique la majorité de tes difficultées

Si tu utilises simplement un texte comprenant un espace, les simples quote suffisent --> ' (mais pas ‘)
Par contre, si tu utilises une variable ($xx) , qui potentiellement contiendra un espace ou des espaces, il faudra utiliser les doubles quotes qui permettent l'expansion de la variable (y compris si elle contient un ou des espaces) dans la chaine de caractère --> (mais pas “).

Si je reprends ton script directement, en y apportant les corrections nécessaires, cela devait fonctionner comme cela :
Code
#!/bin/bash
# une fois ce texte script enregistré en .sh, faire un chmod +x xxx.sh pour le rendre exécutable
# test des paramètres d’entrée
if [ $# != 2 ]
then
echo ‘Erreur: il faut 2 paramètres, le dossier et le fichier des dimensions’
exit
fi

Liste=$(find "$1" -name "G_*.jpg") #liste les fichiers dans les dossiers et sous dossiers

for fichier in "$Liste"
do
produit=$(basename "$fichier"  | cut -c3-8) # pour chaque fichier, extrait le produit = caractères 3 à 8 du nom
pdim=$(grep "$produit" "$2" | cut -c12-100) # cherche via le produit, les dimensions à partir du car 8 (après 6 car de produit et 1 tab)

if [ -z "$pdim" ]
then
echo 'Pas de dimension pour ' "$produit"
else
echo 'dim = '  "$pdim"
echo 'fichier = ' "$fichier"
/usr/local/bin/exiftool -ImageDescription="$pdim" -Overwrite_Original "$fichier"
fi
done
echo 'fin de script'
exit


J'ai également ajouté des doubles quotes autours des variables $1 et $2 pour permettre éventuellement des arguments avec des espaces.
Attention toutefois, pour utiliser un/des arguments avec espace, il faudra également nécessairement utiliser les doubles quotes pour cet argument dans la ligne de commande.

exemple:
Code
maFonction "Argument 1" "Argument 2"

Dis nous si ça fonctionne bien avec ces nouvelles modifications.

Bon courage.

Ce message a été modifié par teddy7545 - 4 Nov 2016, 02:52.


--------------------
MP Intel Dual Xéon 3 GHz - MacOSX 10.10.3 - ATI Radeon HD 5770 - ATTO UL5D - Apple Cinema HD Display 23 pouces
MBP 15' 2017 - MBP 13' mid 2009 - iMac 24' 8,1 2,8GHz - MP G4 MDD Bi 1,25 GHz - MP G4 Quicksylver 933MHz
Go to the top of the page
 
+Quote Post
Jaypee
posté 4 Nov 2016, 06:48
Message #44


Macbidouilleur d'Or !
*****

Groupe : Membres
Messages : 2 486
Inscrit : 29 Aug 2002
Membre no 3 340



Une note en forme de conclusion sur les performances pour un traitement réel de 32000 images

7041,09s user 740,67s system 91% cpu 2:21:44,00 total

Ce temps s'obtient en précédent l'appel au script de la commande time
time find pictures -name "*jpg" -exec /users/jaypee/workspaces/Ruby/dims2exif.sh

Comment générer ces images de test. Reprenez la ligne de Ruby avec la commande touch, il faut utiliser un "cp modele.jpg " au lieu de "touch ".

Validation au hasard:
Code
[jaypee:~/workspaces/Ruby]$ sqlite3 produits.db 'select * from produits where code="999"'
999|50x20x10
[jaypee:~/workspaces/Ruby]$ exiftool -exif:ImageDescription pictures/G_999_12_ZF_1_XYZ.jpg
Image Description               : 50x20x10


Au passage, petite remarque sur le grep:
CODE
[jaypee:~/workspaces/Ruby]$ grep 999 bdproduits.csv
999,50x20x10
1999,50x40x10
2999,50x60x10
3999,50x20x10
4999,50x40x10
5999,50x60x10
6999,50x20x10
7999,50x40x10
8999,50x60x10
9990,10x20x5
9991,20x40x10
9992,30x60x5
9993,40x20x10
9994,50x40x5
9995,10x60x10
9996,20x20x5
9997,30x40x10
9998,40x60x5
9999,50x20x10
10999,50x40x10
11999,50x60x10
12999,50x20x10
13999,50x40x10
14999,50x60x10
15999,50x20x10
16999,50x40x10
17999,50x60x10
18999,50x20x10
19990,10x40x5
19991,20x60x10
19992,30x20x5
19993,40x40x10
19994,50x60x5
19995,10x20x10
19996,20x40x5
19997,30x60x10
19998,40x20x5
19999,50x40x10
20999,50x60x10
21999,50x20x10
22999,50x40x10
23999,50x60x10
24999,50x20x10
25999,50x40x10
26999,50x60x10
27999,50x20x10
28999,50x40x10
29990,10x60x5
29991,20x20x10
29992,30x40x5
29993,40x60x10
29994,50x20x5
29995,10x40x10
29996,20x60x5
29997,30x20x10
29998,40x40x5
29999,50x60x10
30999,50x20x10
31999,50x40x10

Il faut au minimum
grep "^999," pour trouver:
999,50x20x10

Fidèle à mon principe, moins y'a de lignes, moins ça risque de planter, ma solution ne demande que 5 lignes de code, 1 ligne pour créer un bd SQLite, une autre pour créer une table, et deux de mieux pour importer le fichier CSV et elle a des performances connues. En fait seules deux lignes sont ardues:
- Extraire le produit du nom de fichier
prod=`echo $fichier | awk -F _ '{print $2}'`
- Extraire les dimensions de la bd
dims=`sqlite3 ./produits.db "select dimensions from produits where code = '$prod'"`

Dans ces deux lignes, même "pattern". Une commande qui va bien dans un terminal... comment capturer son résultat dans une variable dans un script: Avec l'accent grave
var=<ag><commande qui va bien><ag>, l'absence d'espace entre var et = est importante, sinon var est considéré comme une commande comme cd ou ls...

Merci à tous, en tout cas, j'ai appris plein de choses intéressantes en vous lisant avec ce problème apparemment anodin!

J-P

Ce message a été modifié par Jaypee - 4 Nov 2016, 07:29.
Go to the top of the page
 
+Quote Post
PBell
posté 4 Nov 2016, 15:46
Message #45


Macbidouilleur de bronze !
**

Groupe : Membres
Messages : 264
Inscrit : 7 Dec 2013
Lieu : Ile de France
Membre no 188 169



Grand merci à Teddy7545 : mon script fonctionne grâce à tes conseils !
Effectivement, j'avais mélangé les " et les “ que mes pauvres yeux n'ont pas détectés.

Merci aussi à Jaypee, car tes lignes m'ont indirectement aidées.
Effectivement le '^' du grep que j'avais mis sur le premier script a malencontreusement disparu des mes versions suivantes. Le voilà de retour à sa place !
J'aime bien ton idée de ne pas mettre la boucle dans le script mais d'appeler le script autant de fois que nécessaire. Je me demande cependant si, d'un appel à l'autre, le script reste en mémoire pour des raisons de performances...?

Par ailleurs, si j'ai bien compris la fonction 'awk' que tu utilises, elle est mieux que mon 'cut' qui suppose des longueurs fixes (mais cela faisait partie du descriptif de Speed Monck). Du coup, je me dis qu'il serait aussi judicieux de l'utiliser pour le résultat de mon 'grep'.
Mais dans ce cas, comment specifier que le séparateur -F est une tabulation (ascii 9) ...que je ne peux taper ?

Enfin, ai-je bien compris que le $(commande) pouvait être remplacé par `commande`? Les ag me semblent plus facile à lire (et on sait ce que la lisibilité est primordiale).

Merci à tous pour votre aide et ce cours.
Je ne m'étais jamais vraiment mis au shell, à part qq instructions dans le Terminal souvent appelées via AS.
... Je sens que je vais continuer à jouer un peu ;-)

Cordialement


--------------------
iiMac 24 M1 16Go/1To 13.5.1
iMac 27 i5 3,1GHz 8Go/1To 10.11.6 / 10.6.8
iMac 20 C.Duo 2,6Ghz 8Go/350Go 10.6.8 / 10.11
Mini C.Duo 2,0Ghz 2Go/500Go 10.6.8
Go to the top of the page
 
+Quote Post
Jaypee
posté 5 Nov 2016, 07:44
Message #46


Macbidouilleur d'Or !
*****

Groupe : Membres
Messages : 2 486
Inscrit : 29 Aug 2002
Membre no 3 340



@PBell

Apparemment, awk se comporte aussi naturellement que possible
Code
echo "A\tBC\tD\tE" | awk -F \t '{print $2}'
répond "BC". Il y a une autre méthode plus compliquée, mais celle-ci me convient. Awk utilise en réalité une variable interne FS, et le script awk avant la première accolade, peut commencer par initialiser FS
Code
echo "A\tBC\tD\tE" | awk 'BEGIN{FS="\t"};{print $2}'

Oui le $ ou l'accent grave se comportent comme une fonction "excecute", ils évaluent l'expression enfermée.

Pour la question de performance, il est assez facile de faire des tests et de décider. Ma méthode fait du 4.5 images/s. Si une autre méthode est plus efficace, il faut choisir l'autre méthode. Je ne défends pas la mienne mordicus. Je t'encourage à essayer mon procédé. Copie une image bidon sous 10 noms selon le codage de Speedy Moock et tourne ton script avec time devant. Puis 100, 1000, 3000, puis 10000, puis 32000. Comme tu maitrises les shell fait un script, qui te fabriquera un autre script shell qui fera le boulot. On appelle ça de la méta-programmation, programmer le programme smile.gif Sinon, fait confiance à mon script Ruby.
Code
File.open 'chemin/vers/imagestest.sh', 'w' do |f| (11..16000).each { |i| (11..12).each { |j| f.write "cp chemin/vers/mon/bidon.jpg pictures/G_#{i.to_s}_#{j.to_s}_ZF_1_XYZ.jpg\n" } } end
puis tu exécutes "sh imagestest.sh"

La commande find recherche récursivement sous la racine, et les fichiers jpg ou png ou gif se trouvant n'importe où sous la racine vont à un moment ou un autre être "visités". C'est plus l' illustration du "pattern" visiteur qui est intéressant, surtout si le parcours est "gratuit" fourni par une commande du système.

Enfin cela illustre aussi la notion d'inversion de contrôle qui est extrêmement importante. Ce n'est pas mon code qui doit aller chercher les données mais ce sont les données qui sont apportées à mon code. Dans un monde dit de "big data", c'est la seule approche possible, si les data sont infinies, on ne pourra jamais faire une boucle finie dessus, il faut se contenter d'une seule donnée, puis de la suivante quand elle arrivera...

Je reste attentif aux problèmes intéressants dont la résolution fait avancer la compréhension et la connaissance de la bidouille Mac. La création d'une vraie Interface Graphique avec Xcode, ou une page HTML pourrait conduire à d'autre idées créatives smile.gif PHP peut aider !
Code
<?php
shell_exec("yourscript.sh");
header('Location: http://www.website.com/page?success=true');
?>


J-P

Ce message a été modifié par Jaypee - 5 Nov 2016, 14:27.
Go to the top of the page
 
+Quote Post

2 Pages V  < 1 2
Reply to this topicStart new topic
1 utilisateur(s) sur ce sujet (1 invité(s) et 0 utilisateur(s) anonyme(s))
0 membre(s) :

 



Nous sommes le : 19th March 2024 - 12:43