Manipulation de nom de fichier en TinyScheme sous Gimp

17 08 2010

Scheme ne manipule pas aisément les chaînes de caractères. Sous Gimp, cela ne pose généralement pas de problèmes car la majorité des scripts travaille directement sur une image.

Mais quand on veut travailler sur des fichiers, il faut bien gérer leurs noms et leurs extensions.

Voici quelques fonctions de manipulation de nom de fichier.

Les fonctions

Le code source ci-après définit 3 fonctions :

  • sans-extension,
  • extension,
  • et remplace-extension.

Ces 3 fonctions sont présentées ensemble car extension et remplace-extension utilise sans-extension pour leurs traitements.

sans-extension

La fonctions sans-extension prend un nom de fichier en entrée (nom-fichier) et le retourne après lui avoir ôté son extension, s’il en a une.

Son fonctionnement est proche de la fonction basename d’autres langages à la différence près que sans-extension ne touche aucunement au chemin du fichier. Elle retire uniquement l’extension.

Ex. :

(sans-extension "/home/utilisateur/fichier.jpeg") → "/home/utilisateur/fichier"

extension

La fonction extension fait l’inverse de sans-extension : elle retourne uniquement l’extension du fichier avec son point.

Si le fichier n’a pas d’extension, une chaîne vide est retournée.

Ex. :

(extension "fichier.jpeg") → ".jpeg"

remplace-extension

La fonction remplace-extension change l’extension d’un fichier pour une autre.

Si le fichier n’a pas d’extension, la nouvelle extension est simplement ajoutée.

Cette fonction est utile sous Gimp si vous faites du traitement par lot de fichiers et que vous les convertissiez dans un autre format.

Ex. :

(remplace-extension "fichier.jpeg" ".tiff") → "fichier.tiff"

Code source

; Retourne un nom de fichier sans son extension
(define (sans-extension nom-fichier)
  (let loop ((nom nom-fichier))
    (cond
      ; Si le nom est vide, il n’y a pas d’extension, on retourne le nom complet
      ((string=? nom "") nom-fichier)

      ; Si le dernier caractère est un slash, il n’y a pas d’extension
      ((char=? (string-ref nom (- (string-length nom) 1)) #\/)
        ; on retourne le nom complet
        nom-fichier
      )

      ; Si le dernier caractère est un point
      ((char=? (string-ref nom (- (string-length nom) 1)) #\.)
        ; on retourne le nom en lui enlevant le dernier caractère
        (substring nom 0 (- (string-length nom) 1))
      )

      ; Sinon on supprime le dernier caractère du nom et on boucle
      (else (loop (substring nom 0 (- (string-length nom) 1))))
    )
  )
)

; Retourne l’extension d’un nom de fichier
(define (extension nom-fichier)
  ; Extension=nom de fichier - nom de fichier sans extension
  (substring nom-fichier (string-length (sans-extension nom-fichier)))
)

; Remplace l’extension d’un fichier par une autre
(define (remplace-extension nom-fichier nouvelle-extension)
  (string-append (sans-extension nom-fichier) nouvelle-extension)
)

Fonctionnement

Une boucle particulière

Le fonctionnement des fonctions extension et remplace-extension est trivial, je ne m’attarderai donc pas dessus.

La fonction sans-extension est, quant à elle, plus tordue.

Son principe est de partir de la fin du nom de fichier et de remonter jusqu’à tomber sur un point indiquant le début de l’extension. Sur ce principe, une fonction récursive aurait très bien pu faire l’affaire.

Mais c’était sans compter sur les cas tordus !

Par cas tordus, j’entends :

  • un nom de fichier sans extension, donc sans point (ex. : toto),
  • un nom de fichier sans extension mais dont le chemin contient un point (ex. : /mon.chemin/toto).

Dans ces deux cas, la fonction doit retourner la chaîne telle qu’elle. Ce n’est pas possible avec une fonction récursive qui aura perdu le nom complet en cours de route. Enfin si, c’est possible, mais il faudrait ajouter un deuxième paramètre invariable tout au long des appels récursifs mais l’utilisation de la fonction en serait devenu compliquée.

La fonction sans-extension parcourt donc le nom de fichier de la fin au début au moyen d’une boucle.

Et cette boucle est particulière pour qui est habitué aux langages itératifs ou objets.

Vous connaissez probablement la fonction let* qui permet de créer un bloc d’exécution avec un ensemble de variables locales.

Voici sa petite sœur let, sans l’astérisque ! (je dis “petite sœur” mais on peut voir let* comme une simplification de let)

La fonction let permet aussi de créer un bloc d’exécution avec un ensemble de variables locales. Mais on peut donner un nom à cet ensemble. Dans la fonction sans-extension je l’ai appelée loop (boucle en anglais) pour faciliter la compréhension.

Pour faire un nouveau tour, il suffit d’appeler loop avec les nouvelles valeurs voulues.

Encore de la récursivité ! Et, cette fois, sans utiliser de fonction !

Je vous l’accorde, ce n’est plus de la gymnastique intellectuelle… Celui ou celle qui nous a pondu ça devait pas être très net😉

Les cas possibles

Il y a 4 cas possibles que la fonction gère pour chaque caractère pris à rebours :

  • quand la chaîne de caractère est vide, visiblement, cela veut dire qu’on a analysé tous les caractères sans trouver de point ou de slash, donc pas d’extension ; il faut alors retourner le nom complet,
  • quand le dernier caractère est un slash, cela veut dire que le chaîne de caractère contient un chemin mais que le fichier ne contient pas d’extension ; il faut alors retourner le nom complet,
  • quand le dernier caractère est un point, on a trouvé le point annonçant l’extension du fichier ; il faut retourner la chaîne jusqu’à ce point non inclus,
  • si tous ces tests n’ont rien donné, le dernier caractère n’a aucune fonction particulière, on boucle et on passe au caractère précédent.

Actions

Information

One response

18 08 2010
Parcours d’arborescence en TinyScheme pour Gimp « Le blog de Zigazou

[…] sans-extension présentée dans le billet Manipulation de nom de fichier en TinyScheme sous Gimp, […]

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s




%d blogueurs aiment cette page :