Journal le shell trick tout pourri du vendredi : .lsignore

Posté par . Licence CC by-sa
Tags :
14
24
avr.
2015

Salut,

J'en avais marre de voir des __pycache__ dans mes arborescences python.

[dcp@mb pyaf] $ ls -a
__pycache__ TODO  utils  mnd samples testing umc ...

Pour ne plus les afficher avec ls je me suis souvenu de ça :

[dcp@mb pyaf] $ ls --hide='__pycache__'
TODO  utils  mnd samples testing umc ...

Cette option permet de ne pas lister le motif fournit en argument. Elle peut-être répétée autant de fois que l'on veut.

Voici donc un petit alias dégueu, qui permet de gérer les exclusions à la git : Les items à éliminer de l'affichage sont stockés dans un fichier .lsignore, un par ligne. Un peu comme pour .gitignore donc …

alias ls='ls $(cat $PWD/.lsignore 2>/dev/null | sed -e "s/^/--hide /g")'

A noter: ls -a permet, comme on peut s'y attendre, de s'affranchir de ce filtrage.

  • # Sans UUOC

    Posté par (page perso) . Évalué à 10. Dernière modification le 24/04/15 à 17:10.

    Useless use of cat detected. Sans processus cat inutile, ça donne :

    alias ls='ls $(< $PWD/.lsignore 2>/dev/null sed -e "s/^/--hide /g)'

    Ensuite, je ne vois pas l'intérêt d'utiliser $PWD, donc :

    alias ls='ls $(< .lsignore 2>/dev/null sed -e "s/^/--hide /g)'

    Par ailleurs la précision /g est tout à fait bizarre pour ce genre de remplacement : tu demandes littéralement de remplacer tous les débuts de chaque ligne par --hide. Étant donné qu'une ligne ne peut avoir d'un seul début, c'est vraiment bizarre, et probablement sous-optimal, donc :

    alias ls='ls $(< .lsignore 2>/dev/null sed -e "s/^/--hide /)'

    Enfin, ce serait plus propre avec un test :

    alias ls="ls $(if [ -e .lsignore ]; then while read name ; do printf '--hide %s ' "$file" ; done < .lsignore ; fi)"

    Pas testé…

    • [^] # Re: Sans UUOC

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

      Testé, finalement. Ça marche avec Zsh. :-)

      • [^] # Re: Sans UUOC

        Posté par . Évalué à 7.

        alias ls="ls $(if [ -e .lsignore ]; then while read name ; do printf '--hide %s ' "$file" ; done < .lsignore ; fi)"

        Ta version est clairement meilleure, je me permets de préciser qu'il faut :

        1. remplacer les doubles quote extérieures par des simples (sinon l'interprétation est immédiate et il n'y a plus rien de dynamique),
        2. et qu'il faut ajouter '--' juste derrière le printf pour qu'il n'interprète pas le --hide comme une option.

        sans cela ça ne marche pas (du moins sous bash). On a donc :

        alias ls='ls $(if [ -e .lsignore ]; then while read file ; do printf -- "--hide %s " "$file" ; done < .lsignore ; fi)'

        Pas de cat inutile, pas d'appel à un autre processus, avec ta version. Une dernière simplification anecdotique :

        alias ls='ls $([ -e .lsignore ] && while read file ; do printf -- "--hide %s " "$file" ; done < .lsignore)'
        • [^] # Commentaire supprimé

          Posté par . Évalué à 10. Dernière modification le 24/04/15 à 19:32.

          Ce commentaire a été supprimé par l'équipe de modération.

          • [^] # Commentaire supprimé

            Posté par . Évalué à 2. Dernière modification le 24/04/15 à 19:39.

            Ce commentaire a été supprimé par l'équipe de modération.

            • [^] # Commentaire supprimé

              Posté par . Évalué à 3.

              Ce commentaire a été supprimé par l'équipe de modération.

              • [^] # Re: Sans UUOC

                Posté par . Évalué à 8. Dernière modification le 25/04/15 à 06:19.

                Et apres tout ca, yen a encore qui viennent t'expliquer que les script shell de sysv c'est super simple et facile a ecrire ou lire…

                Linuxfr, le portail francais du logiciel libre et du neo nazisme.

                • [^] # Re: Sans UUOC

                  Posté par . Évalué à 4.

                  Ha toi aussi ton init c’est ~/.bashrc ?

    • [^] # Re: Sans UUOC

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

      alias ls='ls $(< $PWD/.lsignore 2>/dev/null sed -e "s//--hide /g)'

      Franchement c'est plus simple et clair comme ca :

      alias ls='ls $(sed -e "s//--hide /g" $PWD/.lsignore)'

      • [^] # Re: Sans UUOC

        Posté par . Évalué à 3.

        Oui, j'aime beaucoup :-). Juste ajouter la redirection en cas d'absence de .lsignore, enlever l'option globale de sed, le $PWD qui n'apporte rien et voilà :

        $ alias ls='ls $(sed -e "s/^/--hide /" .lsignore 2>/dev/null)'
        • [^] # Re: Sans UUOC

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

          Sauf que ça laisse un processus sed dont on pourrait parfaitement se passer. Perso, quand j'écris des trucs en shell, je préfère autant que possible éviter de lancer des processus, surtout pour des tâches simples à réaliser à l'intérieur du shell.

          • [^] # Re: Sans UUOC

            Posté par . Évalué à 1.

            Oui, cf ma réponse à ta première intervention.

          • [^] # Re: Sans UUOC

            Posté par . Évalué à 5.

            Tu lance pourtant déjà systématiquement un processus, alors que ça peut se remplacer par une fonction…
            Personnellement je suis loin d'être aussi extrémiste que toi, ce n'est pas parce que le shell (ou un shell particulier) possède une syntaxe simple pour faire un traitement qu'il est préférable de lui faire faire. Il arrive assez facilement que le coût du fork()/exec() soit inférieur à la lenteur du shell, notamment quand tu fait des boucles en shell.

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

    • [^] # Re: Sans UUOC

      Posté par (page perso) . Évalué à 8. Dernière modification le 25/04/15 à 15:24.

      Juste pour le jour où les gens en auront marre de déboguer des scripts shell avec 14 niveaux d'indirection:

      On peut introduire une fonction auxiliaire pour préparer la ligne de commande:

      __ls_prepare_argv()
      {
        if [ -e .lsignore ]; then
          while read name ; do printf -- '--hide %s ' "$file"; done < .lsignore
        fi
      }
      alias ls='ls $(__ls_prepare_argv)'
      

      ça a la vertu d'être plus facile à tester et plus facile à lire, grâce au nom de la fonction. Sinon, lorsque les fichiers n'ont pas d'espaces dans leur nom, on peut simplifier:

      __ls_prepare_argv()
      {
        if [ -e .lsignore ]; then
          xargs printf -- '--hide %s ' < .lsignore
        fi
      }
      alias ls='ls $(__ls_prepare_argv)'
      

      Useless use of cat detected.

      Tu ne serais pas en train d'utiliser une expression anglaise sur un site francophone, hmm? Comme ça, subrepticement? Sans même mettre des italiques en plus! ☺

  • # question idiote

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

    Ne vaudrait-il pas mieux faire un alias sur une commande différente, par exemple alias lsi=… comme cela reste disponible la vraie commande ?

    J'imagine, et je m'y vois tellement, un moment ou ce que l'on occulte dans le ls manque dans un contexte ou c'est vraiment nécessaire et je me voie tourner l'après-midi pour comprendre ce qui ne va pas tellement habitué à ne pas le voir apparaître que je passerais à coté de cette évidence ? il reste alors la vraie commande ls ?

    • [^] # Re: question idiote

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

      Tu peux toujours appeler le vrai ls avec \ls ou /bin/ls.

      Je pense que si tu as l'habitude de taper lsi et que tu ne vois pas ce qui ne va pas, tu continueras à taper lsi parce que c'est ce que tu es habitué à faire…

      • [^] # Re: question idiote

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

        Tu peux toujours appeler le vrai ls avec \ls ou /bin/ls.

        Il y aussi command ls que je mentionne car beaucoup ne le connaissent pas.

  • # Tu peux utiliser FIGNORE à la place de ton fichier

    Posté par . Évalué à 7.

    La variable d'environnement FIGNORE est destinée à ce type de filtrage au moment de la complétion.
    Tu peux certainement la réutiliser ici pour l'écriture de ton alias.

    Le plus simple est de convertir vers un tableau ce qui facilitera l'expansion de la variable.

    Sous Bash:

    alias ls="IFS=: read -a fignore <<< $FIGNORE; ls ${fignore[@]/#/--hide=}"

    Sous Zsh, le tableau fignore est directement défini, ce qui rend ton alias encore plus concis:

    alias ls='/bin/ls --hide=${^fignore}'

    Un autre avantage du tableau est qu'il te permet de le modifier facilement à la volée:

    fignore+=__pycache__

    P.S. Les guillemets simples ou doubles ont leur importance ici.

  • # Éxecution de code par le propriétaire du dossier

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

    En théorie, tu donne ton shell à quiconque contrôle un dossier depuis lequel tu ls. En pratique ça a peu de chance d'être exploité.

Suivre le flux des commentaires

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