Journal Retour à l'interface Console

Posté par . Licence CC by-sa
32
4
août
2013

Chers geekettes et geeks

Par erreur j'ai effacé mon script bricolage shell qui m'était utile pour détecter/supprimer mes fichiers dupliqués.

Je décide donc de le refaire en mieux => quitte à faire mieux, faisons des choix techniques bien réfléchis.

D'abord le langage :
1. Python 3 est bien mature => Mais quelle interface graphique prendre ?
2. Rust est potentiellement LE langage d'avenir => Mais est-ce que l'API permet de le faire facilement ?
3. webapp (JavaScript) pour être le plus portable possible même pour FirefoxOS => Mais l'API JavaScript ne semble pas adaptée pour comparer le contenu de fichiers…
4. Ruby est le langage préféré des webmaster LinuxFr
5. Go reçoit le soutien financier d'une grosse entreprise compétente dans ses choix techniques (Google)
6. …

Puis, le choix de l'interface graphique :
1. EFL
3. Qt
2. GTK+
4. … et je tombe sur PyZenity

Découverte : un script shell peut avoir une interface graphique avec zenity. Mais aussi avec yad

Allez, voici donc la petite histoire :

Au tout début (le début des année 90), il y avait dialog qui permettait aux scripts shell, déjà à l'époque, d'afficher de jolis écrans ASCII en utilisant curses, puis ncurses.

Plein de projets s'en inspirèrent, citons en quelques uns :

  • cdialog qui semble toujours actif depuis 20 ans et qui est l'origine d'une erreur d'orthographe (guage à la place de gauge) que se traine depuis le man dialog pour compatibilité !

  • xdialog (admirez le beau site web) est un port vers GTK+

  • gdialog que ploum nous présentait il y a 10 ans déjà !

  • kdialog Pas de jalou, KDE a aussi droit à son gdialog.

  • 'zenity` apporte pas mal de nouveautés et dépasse les précédentes solutions graphiques.

  • yad apparait (fork) lors que le projet zenity est inactif. yad commence par supprimer la dépendance à des bibliothèques obsolètes et apporte progressivement de nouvelles fonctionnalité. Depuis, zenity s'est réveillé et les deux projets sont tous deux actifs mais ont tendance à partir dans des directions quelques fois différentes.

  • whiptail est le véritable concurrent de dialog. Tous les autres projets présentés ci-dessus apportent une interface graphique. Mais pour l'affichage ASCII, dialog régnait en maître. whiptail est l’œuvre du projet Debian afin d'obtenir des installeur moins gourmand en mémoire (en réduisant les possibilités et en utilisant newt à la place de ncurses par exemple).

Mais Thomas Dickey, le mainteneur de dialog défend son bébé et voici ce qu'il a écrit en substance dans le man dialog :

C'est alors qu'il y a whiptail.
Sa documentation prétend que c'est un (a) remplaçant plus léger à dialog et (b) qu'il est compatible avec dialog à part quelques fonctionnalités.
Le (a) est faux en comparant le tailles actuelles (Debian 2007). Le total pour whiptail, newt, popt et slang est de 757 Kio. dialog et ncurses totalisent 520 Kio.
Le (b) est trompeur car whiptail ne supporte pas les options génériques de dialog. En fait, whiptail est d'avantage compatible avec le dialog de 1994 (v0.4) qu'avec le dialog d'aujourd'hui.

J'ai donc décidé de revenir au langage shell (bash) et de tester ces différentes alternatives.

Et comme j'aime utiliser la console, mon script bricolage se lance à la ligne de commande. Et donc, c'est plus logique de rester avec une interface en mode console.

L'interface console est d'ailleurs plus pratique et plus efficace. Peut être moins joli, mais ça fait bien son job :-)

Et c'est dialog qui a gagné !

Est-ce que ce journal vous a plu ?
Est-ce que ça vaut le coup de s'en inspirer pour écrire une Dépêche ? (la partie historique)
Quels sont vos expériences sur les interfaces ? graphique ou console ?
Quel langage auriez vous utilisé pour pour détecter des fichiers dupliqués et aider l'utilisateur à choisir lesquels à effacer ?

  • # Alors....

    Posté par (page perso) . Évalué à 5.

    Est-ce que ce journal vous a plu ?

    Oui

    Est-ce que ça vaut le coup de s'en inspirer pour écrire une Dépêche ? (la partie historique)

    Oui, si tu développes un peu plus et rajoute des liens vers (ou directement imbrique) des images, voire si tu montres un chouilla de code expliquant comment ils diffèrent à l'usage.

    Quels sont vos expériences sur les interfaces ? graphique ou console ?

    ncurses codé à la mano… Pas beaucoup, d'ailleurs.

    Quel langage auriez vous utilisé pour pour détecter des fichiers dupliqués et aider l'utilisateur à choisir lesquels à effacer ?

    Perl, bien sûr ! Aucun besoin d'apprendre un autre langage…
    À la limite, mon shell, si le script n'a à offrir aucune fonctionalité supplémentaire et/ou non-triviale.

    • [^] # Re: Alors....

      Posté par (page perso) . Évalué à 3.

      Je plussoie pour la dépêche détailée.

      Parmi les détails, tu peux retrouver le code source original de chaque version, et chercher un peu s'il y a des liens de paternité entre les différents codes source.

      Quel langage auriez vous utilisé pour pour détecter des fichiers dupliqués et aider l'utilisateur à choisir lesquels à effacer ?

      Le shell, sans interface curses.

  • # Gtkdialog

    Posté par . Évalué à 8. Dernière modification le 04/08/13 à 10:39.

    Tu as oublié gtkdialog à ta liste. Lui aussi revient d'entre les morts.

    Quel langage auriez vous utilisé pour pour détecter des fichiers dupliqués et aider l'utilisateur à choisir lesquels à effacer ?

    Cela aurait été un front-end à duff en lua-lgi. Le seul problème est que la sortie console de duff me plaît bien.

    Est-ce que ce journal vous a plu ?

    Je cherche en vain les boutons twitter et facebook pour en parler autour de moi. Ce sera donc le fallback pertinent.

    The capacity of the human mind for swallowing nonsense and spewing it forth in violent and repressive action has never yet been plumbed. -- Robert A. Heinlein

    • [^] # Re: Gtkdialog

      Posté par . Évalué à 7.

      Tu as oublié gtkdialog à ta liste.

      Tout à fait d'accord surtout qu'il est très différent de zenity, il permet de faire des interfaces plus évoluées (ou plus originales) que de se baser sur les interfaces prédéfinies de zenity (ou alors j'ai raté un paragraphe du man de zenity).

      Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

  • # Réponses

    Posté par . Évalué à 4.

    Est-ce que ce journal vous a plu ?

    Oui !

    Est-ce que ça vaut le coup de s'en inspirer pour écrire une Dépêche ? (la partie historique)

    Éventuellement. Avec plus d'anecdotes et en rentrant plus dans le détail pour comprendre les raisons de ces multiples solutions, il serait possible d'en faire une excellente dépêche, qui contribuerait à la culture des moules.

    Quels sont vos expériences sur les interfaces ? graphique ou console ?

    Ce sont encore des catégories trop vastes. Par exemples, en console, tu peux ou bien faire une super commande en ligne pour exécuter ton programme une bonne fois pour toute, ou bien dérouler un programme chiant lisant les entrées clavier au fur-et-à-mesure. Le choix de l'interface dépend de l'utilisateur ciblé.

    Quel langage auriez vous utilisé pour pour détecter des fichiers dupliqués et aider l'utilisateur à choisir lesquels à effacer ?

    J'aurais rien utilisé, car j'aurais pas eu de fichiers dupliqués :-o

  • # Quel langage auriez vous utilisé pour pour détecter des fichiers dupliqués et aider l'utilisateur à

    Posté par (page perso) . Évalué à 10.

    J’aurai utilisé fdupes qui est fait pour ça.

  • # question supplémentaire

    Posté par (page perso) . Évalué à 3.

    Dans les programmes présentés, est-ce qu'il y en a qui permettent d'utiliser indifféremment une interface graphique ou une interface console (avec le même code) ? Je suis allé sur les pages de Yad et Zenity mais je n'ai rien trouvé après un rapide coup d'oeil.

    « I approve of any development that makes it more difficult for governments and criminals to monopolize the use of force. » Eric Raymond

    • [^] # Re: question supplémentaire

      Posté par . Évalué à 2.

      Je n'ai pas trouvé non plus un utilitaire du type dialog qui permette les deux modes : graphique et console.

      Par contre, il y a une alternative : utiliser la même API (options passés à la ligne de commande) commune à un utilitaire en mode graphique et un utilitaire en mode console. Dans certains exemples que j'ai trouvé, le script shell vérifie quels sont les utilitaires présents avec which (ou type) par exemple :

      DIALOG=$(type -p cdialog xdialo gdialog dialog zenity gtkdialog yad whiptail 2>&- | head -1)
      
      "$DIALOG" --title "Le titre" --infobox "Le contenu du message" 4 20
      

      Malheureusement, les options des commandes zenity (ou yad) ne sont pas vraiment compatibles avec dialog :-( Il faudrait étudier de plus près les autres utilitaires gdialog, gtkdialog… Par exemple, dialog utilise les options height width en nombre de caractères, alors que les autres utilisent ces options dans le sens inverse (width height) et en pixels ! Mais bon, il y a peut être un mode de compatibilité que je n'ai pas vu…

  • # revoilà ton script perdu, sous la même licence que Perl (GPLv1+|Artistic licence)

    Posté par . Évalué à 4.

    #!/usr/bin/perl
    
    use v5 ;
    use strict ;
    
    ######################
    # User configuration #
    ######################
    my $temporary_file = "/tmp/list_findduplicate_md5" ;
    
    # can be any of the control sum programs from coreutils:
    # cksum, sha1sum, sha224sum, sha256sum, sha384sum, sha512sum, md5sum
    # could be sha3 as well the day GNU decides to add it to coreutils.
    my $hash_program = "md5sum" ;
    #my $hash_program = "/usr/local/bin/messageid.sh" ;
    # program must display the name of the file after its sum.
    # When using cksum only the crc32 sum is used, not the byte count.
    
    ########
    # Main #
    ########
    sub help {
      my $help_string="
    Syntax : ./findduplicate.pl
    Will list files in current directories and subdirectories,
    and display the location of the files which are duplicates,
    based on their hash calculated by ${hash_program}.
    
    Author: XXXXXXXXXXXX, <xxxxxxxxxxxx\@xxxxxxx>
    Date: 19 May 2013
    " ;
      print $help_string ;
      exit (0) ;
    }
    
    help() unless ($#ARGV == -1) ;
    
    my ($line) ;
    my (@params) ;
    my ($formersum,  $currentsum) ;
    my ($formername, $currentname) ;
    my ($count) = 0 ;
    my ($s1, $s2) ;
    
    # Fichier contenant les sommes de contrôle de tous
    # les fichiers du répertoires et des sous-répertoires,
    # classées par ordre alphabétique de la somme de contrôle
    system ("find . -type f -exec ${hash_program} \"{}\" \";\" | sort > ${temporary_file}") ;
    open INPUT, "<", $temporary_file ;
    $formersum = "" ;
    while ($line = <INPUT>) {
      # Dans cette boucle on lit une somme de contrôle
      # depuis le fichier, et on compare à la précédente.
      # C'est ce qui définit un fichier dupliqué.
      chomp $line ;
      @params = split / /, $line ;
      $currentsum  = $params[0] ;
      $currentname = $params[$#params] ;
      #print "##${formersum} -- ${currentsum}**\n" ;
      if ("${formersum}" eq "${currentsum}") {
        $s1 = -s ${formername} ;
        $s2 = -s ${currentname} ;
        # Dans le cas où on utilise messageID.sh, on peut
        # avoir des fichiers dupliqués de taille différente.
        # Par convention on écrit le plus petit en premier.
        # Dans les autres cas (md5, crc32), les fichiers
        # détectés comme dupliqués ont nécessairement la
        # même taille, la première comparaison étant alors
        # toujours vraie.
        #
        if ($s1 <= $s2) {
        print "diff -u ${formername} ${currentname}\n" ;
        } else {
        print "diff -u ${currentname} ${formername}\n" ;
        }
        #print "mv ${formername} dup/\n" ;
        $count = $count + 1 ;
      }
      $formersum = $currentsum ;
      $formername = $currentname ;
    }
    if ($count == 0) {
      print "No duplicates found\n" ;
    }
    #elsif ($count == 1) {
    #  print "One duplicate found\n" ;
    #} else {
    #  print "$count duplicates found\n" ;
    #}
    
    # On the target system, asks for enter
    # Useful on a specific machine where the script
    # is run from a graphical menu and must wait for
    # user to read the results before existing.
    #
    #print "Press Enter to exit\n" ;
    #<> ;
    
    __END__```
    • [^] # messageid.sh

      Posté par . Évalué à 4.

      Au cas où, le script référencé (en option) qui détecte les messages Maildir en double.

      #!/bin/sh
      # Renvoie le messageid d'un message Maildir,
      # à fins de déduplication
      
      case $# in
              1) file=$1
              ;;
              *) echo -e "Message-id of a maildir message.\n Syntax: messageid.sh FILE\n"
              ;;
      esac
      
      id=$(grep --no-messages --no-filename --colour=never --max-count 1 "^Message-I[dD]: " $file | sed "s/^.* //")
      echo $id $file
  • # Mes réponses

    Posté par . Évalué à 4.

    Est-ce que ce journal vous a plu ?

    Oui mais j'aurais bien aimé voir les sources de ton script :)

    Est-ce que ça vaut le coup de s'en inspirer pour écrire une Dépêche ? (la partie historique)

    Oui avec gtkdialog et des exemples de code pour chacun.

    Quels sont vos expériences sur les interfaces ? graphique ou console ?

    Jamais fait d'interface graphique console (type curse) pour les autre j'ai un peu utilisé zenity et gtkdialog mais très peu et uniquement pour des programmes que je ne lance pas depuis un terminal, mais depuis un gestionnaire de fichier par exemple (mais comme j'en utilise plus).

    Quel langage auriez vous utilisé pour pour détecter des fichiers dupliqués et aider l'utilisateur à choisir lesquels à effacer ?

    Du shell et zsh probablement, mais sans interface. Par contre j'ai plutôt tendance à ne pas supprimer les fichiers mais plutôt à créer des liens en dur à la place. Quelque chose un peu comme ça :

    #!/usr/bin/zsh
    
    autoload zargs
    
    typeset -A index
    
    function dedup_file () {
        typeset -a infos
        infos=( "${(s:  :@)$(sha256sum "$1")}" )
        if [[ -f "${index[${infos[1]}]}" ]] ; then
            rm "${infos[2]}"
            ln -v "${index[${infos[1]}]}" "${infos[2]}"
        else
            index["${infos[1]}"]="${infos[2]}"
        fi
    }
    
    zargs -n1 -- **/*(.) -- dedup_file

    Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

    • [^] # Re: Mes réponses

      Posté par . Évalué à 1.

      Le code source est librement disponible :
      https://github.com/olibre/ShellScripts/blob/master/rmdups.sh
      (je ne voulais pas montrer tout de suite le code dans le journal de peur que les commentaires divergent trop vite vers l'algorithmique)

      C'est une bonne idée d'utiliser les tableaux, je me suis embêté avec des fichiers intermédiaires ! Très joli/concis ton script zsh. Je te préviens, le mien ressemble plus à du bricolage, pas très maintenable. Je veux bien que tu apportes des améliorations/simplifications ;-)

      Oui, c'est une bonne idée les liens en dur, surtout quand cela concerne les fichiers des applications comme ceux des répertoires ~/.* Mais quand ce sont des photos, vidéos, musiques, documents, codes source (…) on a envie de faire le ménage et réduire le nombre de fichiers.

      Arcaik et saim m'ont fait découvrir fdupes et rmlint. En ré-utilisant ces outils j'aurais été plus rapide pour implémenter ma sur-couche !

      Il me vient une idée : journal ou dépêche pour expliquer les différentes solutions sur l'éradication des fichiers dupliqués. Surtout que le patrimoine numérique de chacun commence à exploser, qu'il est composé de fichiers archivés N fois et retrouvés sur des clefs USB, e-mails et recopiés un peu partout. Et en plus, tout doit rentrer dans un petit SSD… C'est une sous partie d'un sujet plus vaste : Comment bien organiser son patrimoine numérique (backup, nettoyage…)

  • # dmenu

    Posté par . Évalué à 3.

    Tu aurais aussi pu citer dmenu.

    Suffisant pour faire de simples menus. Bon, il faut aimer le style moche sobre. Le truc sympa, c'est que tu peux sélectionner un item en tapant le début de son nom (pratique si tu dois faire des menus avec des longues listes, et que ton clavier n'a pas tendance à se blo

  • # Déduplication

    Posté par (page perso) . Évalué à 5.

    Il faut voir quel est est le besoin. S’il s’agit de repérer quelques fichiers utilisateurs qui pourraient avoir été dupliqués, pourquoi pas… Par contre, si l’on se trouve dans un environnement où potentiellement de nombreux fichiers sont concernés, mieux vaut utiliser un système de fichiers moderne tel que ZFS.

  • # Correction

    Posté par . Évalué à 2. Dernière modification le 05/08/13 à 14:37.

    Pour info le renvoi depuis le site Python est devenu obsolète, il faut maintenant se rendre
    ici

    Est-ce que ce journal vous a plu ?

    oui pas mal, comme d'autres je pense que détailler avec du script serait mieux.

    Est-ce que ça vaut le coup de s'en inspirer pour écrire une Dépêche ? (la partie historique)

    pour moi : oui

    Quels sont vos expériences sur les interfaces ? graphique ou console ?

    Qt surtout, Silverlight ( mais bon…), toute la clique Cocoa & Cocoa Touch

    Quel langage auriez vous utilisé pour détecter des fichiers dupliqués et aider l'utilisateur à choisir lesquels à effacer ?

    Selon la complexité recherchée: d'abord en Bash et si je veux affiner ajouter plus de fonctionnalités : Python sans conteste. Ceci est issus d'un vécu de ce type d'expériences: j'avais besoin d' un moyen de prévenir des utilisateurs que le build de mon code avait changé.
    Comme décrit, j'ai donc commencé naturellement en bash (pensant à Ncurses par la suite) ayant vite été découragé par la syntaxe et donc la difficulté au débogage inhérente à celle-ci, je me suis d'abord intéressé à Ruby qui ne m'a pas semblé apporter plus de choses que Python, qui reste vraiment mon favori, en quelques lignes j'ai pu faire un script pour :
    - Lancer ma compilation avec les couleurs ( pas vraiment simple avec Bash, tandis que Lint…)
    - récupérer les erreurs les plus importantes, (qmake et make sont verbeux)
    - récupérer sa version auto-incrémentée
    - envoyer un email à un ensemble d'utilisateurs depuis une liste définie en texte à part
    - transmettre l'émail avec un joli logo (inutile mais donne un aspect plus sérieux), un message html préformaté
    avec la nouvelle version ajournée
    - copie les exécutables dans leurs répertoires respectifs

    Je suis certain que Ruby, Perl, Bash, et d'autres le font également ; Cependant pour les avoir essayés seul Python et sa philosophie "simple" ma permis de passer de l'idée à la réalisation aussi vite et simplement.

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.