Forum Linux.général less demande un suffixe pour lire utf8... et le lit correctement sans!? [en fait, c'est lesspipe.sh]

Posté par  . Licence CC By‑SA.
Étiquettes :
1
2
mai
2022

Bonjour.

Sur mon installation Manjaro (elle est à jour, j'ai vérifié), je viens de constater que less me demande d'ajouter le suffixe '::' à un fichier texte utf-8:

==> append :: to filename to view the utf-8 encoded file

Je fais ça et effectivement, j'ai plus le message. Mais il le lit quand-même correctement sans ça…! [Heureusement qu'il ne me demande pas de courir tout nu dans le quartier en chantant "The Great Pretender", ma crédulité a ses limites.]

Je suis allé faire un tour du côté de StackOverflow et j'ai vérifié les étapes données dans la réponse: ni 'LESSCHARSET=utf8 less <monfichier>' ni 'LESSCHARSET=utf-8 less <monfichier>' ne changent quoi que ce soit.

J'ai vérifié mes "locales" et toutes sont en .utf8 (depuis le premier jour de l'installation, d'ailleurs):

locale -a | grep fr_
fr_BE.utf8
fr_CA.utf8
fr_CH.utf8
fr_FR.utf8
fr_LU.utf8

Par acquit de conscience, j'ai ré-exécuté locale-gen, rien à faire: j'ai toujours le même message. Voici ce que j'ai:

$ cat /etc/locale.conf
LANG=fr_BE.utf8
LC_ADDRESS=fr_BE.utf8
LC_IDENTIFICATION=fr_BE.utf8
LC_MEASUREMENT=fr_BE.utf8
LC_MONETARY=fr_BE.utf8
LC_NAME=fr_BE.utf8
LC_NUMERIC=fr_BE.utf8
LC_PAPER=fr_BE.utf8
LC_TELEPHONE=fr_BE.utf8
LC_TIME=fr_BE.utf8

Noter que j'ai beau remplacer utf8 par UTF-8 et vice-versa (comme à l'installation), ça ne change strictement rien. Mais ce qui me surprend c'est que less affiche bien les accents et les caractères spéciaux… Je pige plus rien. C'est quoi son stress au p'tit less?

Si quelqu'un a une idée, je suis preneur.

EDIT: J'ai fini par trouver d'où vient le message et je pense avoir compris pourquoi il est affiché.

Tout part de /usr/bin/lesspipe.sh, un script-à-tout-faire qui permet de visualiser à peu près n'importe quel fichier, pourvu qu'il y ait un décodeur pour ça. J'ai plus ou moins tracé le code jusqu'à la fonction get_unpack_cmd (ligne 271):

get_unpack_cmd () {
    fchar="${1%:*}"; fchar="${fchar#*:}"
    fcat="${1##*:}"
    x="${1%%:*}"
    cmd=
    if [[ "$3" == $sep$sep ]]; then
        return
    fi
    declare t
    # uncompress / transform
    case $x in
        gzip|bzip2|lzip|lzma|xz|brotli|compress)
            # remember name of uncompressed file
            [[ $2 == - ]] || fileext="$2"
            fileext=${fileext%%.gz}; fileext=${fileext%%.bz2}
            [[ $x == compress ]] && x=gzip
            has_cmd $x && cmd=($x -cd "$2") && return ;;
        zstd)
            has_cmd zstd && cmd=(zstd -cdqM1073741824 "$2") && return ;;
        lz4)
            has_cmd lz4 && cmd=(lz4 -cdq "$2") && return ;;
        xlsx)
            has_cmd in2csv && cmd=(in2csv -f xlsx "$2") && return
            has_cmd excel2csv && cmd=(istemp excel2csv "$2") && return ;;
        ms-excel)
            has_cmd in2csv && cmd=(in2csv -f xls "$2") && return
            has_cmd xls2csv && cmd=(istemp xls2csv "$2") && return ;;
    esac
    # convert into utf8

    if [[ -n $lclocale && $fchar != binary && $fchar != *ascii && $fchar != $lclocale && $fchar != unknown* ]]; then
        qm="\033[7m?\033[m" # inverted question mark
        rep=-c
        trans=
        echo ""|iconv --byte-subst - 2>/dev/null && rep="--unicode-subst=$qm --byte-subst=$qm --widechar-subst=$qm" # MacOS
        echo ""|iconv -f $fchar -t $locale//TRANSLIT - 2>/dev/null && trans="-t $locale//TRANSLIT"
        msg "append $sep$sep to filename to view the $fchar encoded file"
        cmd=(iconv $rep -f $fchar $trans "$2")
        # loop protection, just in case
        lclocale=
        return
    fi
    [[ "$3" == $sep ]] && return
    file2=${3#$sep}
    file2=${file2%%$sep*}
    # remember name of file to extract or file type
    [[ -n "$file2" ]] && fileext="$file2"
    # extract from archive
    rest1="$rest2"
    rest2=
    prog=
    case "$x" in
        tar)
            prog=tar
            has_cmd bsdtar && prog=bsdtar ;;
        rpm)
            { has_cmd cpio && has_cmd rpm2cpio; } ||
            { has_cmd bsdtar; } && cmd=(isrpm "$2" "$file2") ;;
        java-archive|zip)
            { has_cmd bsdtar && prog=bsdtar; } ||
            { has_cmd unzip && prog=unzip; } ;;
        debian*-package)
            { has_cmd ar || has_cmd bsdtar; } && cmd=(isdeb "$2" "$file2") ;;
        rar)
            { has_cmd bsdtar && prog=bsdtar; } ||
            { has_cmd unrar && prog=unrar; } ||
            { has_cmd rar && prog=rar; } ;;
        ms-cab-compressed)
            { has_cmd bsdtar && prog=bsdtar; } ||
            { has_cmd cabextract && prog=cabextract; } ;;
        7z-compressed)
            { has_cmd 7zr && prog=7zr; } ||
            { has_cmd 7z && prog=7z; } ||
            { has_cmd 7za && prog=7za; } ;;
        iso9660-image)
            { has_cmd bsdtar && prog=bsdtar; } ||
            { has_cmd isoinfo && prog=isoinfo; } ;;
        archive)
            prog=ar
            has_cmd bsdtar && prog=bsdtar
    esac
    [[ -n $prog ]] && cmd=(isarchive $prog "$2" "$file2")
    if [[ -n $cmd ]]; then
        [[ -n "$file2" ]] && file2= && return
        msg "use ${x}_file${sep}contained_file to view a file in the archive"
        has_cmd archive_color && colorizer=archive_color || colorizer=cat
    fi
}

C'est le test de la ligne 301 qui génère le message:

if [[ -n $lclocale && $fchar != binary && $fchar != *ascii && $fchar != $lclocale && $fchar != unknown* ]]

Le premier paramètre passé à la fonction est un triplet dont le séparateur est le double point (':'). L'élément médian identifie le type de fichier à afficher. En gros le test dit ceci:

  • si le paramètre régional existe ET
  • si le type de fichier n'est pas binaire ET
  • si le type de fichier n'est pas ASCII' ET
  • si le paramètre régional ($lclocale) est différent du type de fichier ($fchar) ET
  • si le format de fichier n'est pas inconnu,
  • ALORS afficher un message d'avertissement.

Le seul souci c'est que mon paramètre régional est détecté comme 'utf8' et le type de fichier comme 'utf-8'! Et comme les deux sont lexicalement différents, le message est affiché.

Mais bon, ce script est totalement imbitable (en outre, du code pissé par blocs sans une seule ligne de commentaire expliquant ce qui s'y passe), j'ai pas trop envie de mettre les doigts dedans et de casser quelque chose. Je vais probablement adresser un avis de bug à ma distribution préférée, qui transmettra au mainteneur, je présume.

  • # Quel less ?

    Posté par  . Évalué à 4. Dernière modification le 02 mai 2022 à 17:09.

    En passant rapidement sur la question, la première chose à laquelle je pense est de vérifier de quel less il s'agit. Est-ce que tu n'aurais pas un autre less dans ton PATH, ou un alias, ou encore une commande builtin de ton shell, qui se comporterait étrangement ?

    Edit: si ton shell est Bash, par exemple, que dit command -V less ?

    • [^] # Re: Quel less ?

      Posté par  . Évalué à 2.

      Mon shell est zsh.

      which less

      me renvoie /usr/bin/less et je n'en ai pas d'autre. C'est la version 590 qui est présente sur mon système.

      Et si je tape

      /usr/bin/less <n'importe_quel_fichier_utf8>

      j'ai en effet le marqueur de rappel qu'il me faut ajouter le suffixe '::'…

      • [^] # Re: Quel less ?

        Posté par  . Évalué à 2.

        D'accord et le message est une citation exacte ? Parce que j'avais regardé et je ne trouve aucune référence dans le code source de less. Ni dans celui de la glibc, d'ailleurs.

        Je n'ai pas trouvé où Manjaro range le PKGBUILD, mais si c'est le même que celui d'Archlinux, y'a pas non plus de patch spécial.

        Donc c'est assez bizarre, oui :-D

        • [^] # Re: Quel less ?

          Posté par  . Évalué à 2.

          Et si c'était systemd (ou un de ses composants) qui s'occupait encore de ce qui ne lui regarde pas? Ce serait pas la première fois…

        • [^] # Re: Quel less ?

          Posté par  . Évalué à 2. Dernière modification le 11 mai 2022 à 13:31.

          Je viens d'approfondir la recherche avec cette commande:

          which less | xargs ldd | grep -oE '(/\w+)+([.-]|\w+)*' | xargs strings | grep -i 'append'

          En gros: «donne-moi toutes les chaînes de caractères contenant le motif "append" dans tous les binaires liés à et chargés par less»… Ben je trouve rien non plus!

          • [^] # Re: Quel less ?

            Posté par  . Évalué à 4.

            Vérifie si less utilise un préprocesseur, c’est peut-être ce préprocesseur qui affiche ce message. As-tu une variable LESSOPEN dans ton environnement, et si oui que contient-elle ?

            • [^] # Re: Quel less ?

              Posté par  . Évalué à 4.

              Note to self : toujours rafraîchir la page avant de poster un message… ><

        • [^] # Re: Quel less ?

          Posté par  . Évalué à 2.

          J'ai bien une idée pour savoir d'où vient ce message mais j'ignore comment faire exactement: il devrait être possible d'exécuter less sous gdb et de provoquer un point d'arrêt dès que le message en question est affiché, non?

        • [^] # Re: Quel less ?

          Posté par  . Évalué à 5.

          Ça y est, j'ai trouvé! C'est le script lesspipe.sh qui affiche ce message à la con. Ce script, bien pratique, parce qu'il permet de passer à less un peu n'importe quel type de fichier, contient la section suivante:

              if [[ -n $lclocale && $fchar != binary && $fchar != *ascii && $fchar != $lclocale && $fchar != unknown* ]]; then
                  qm="\033[7m?\033[m" # inverted question mark
                  rep=-c
                  trans=
                  echo ""|iconv --byte-subst - 2>/dev/null && rep="--unicode-subst=$qm --byte-subst=$qm --widechar-subst=$qm" # MacOS
                  echo ""|iconv -f $fchar -t $locale//TRANSLIT - 2>/dev/null && trans="-t $locale//TRANSLIT"
                  msg "append $sep$sep to filename to view the $fchar encoded file"
                  cmd=(iconv $rep -f $fchar $trans "$2")
                  # loop protection, just in case
                  lclocale=
                  return
              fi

          Reste à voir ce que tout ça signifie, me faudra un peu de temps pour l'analyser.

          • [^] # Re: Quel less ?

            Posté par  (site web personnel, Mastodon) . Évalué à 3.

            Faut voir ce qui est mis dans $lclocale et $fchar avant ce test. Et aussi vérifier si tu as iconv qui est installé.

            “It is seldom that liberty of any kind is lost all at once.” ― David Hume

            • [^] # Re: Quel less ?

              Posté par  . Évalué à 3.

              Exact. C'est fait. J'ai mis à jour mon message initial avec mes explications.

              • [^] # Re: Quel less ?

                Posté par  (site web personnel, Mastodon) . Évalué à 3.

                Arf, semble que plus personne ne l'a utilisé depuis qu'on ne fait plus de latinX

                “It is seldom that liberty of any kind is lost all at once.” ― David Hume

Suivre le flux des commentaires

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