Journal Des "basheries"

Posté par  . Licence CC By‑SA.
Étiquettes :
89
29
nov.
2016

Sommaire

Salut,

Voici un journal qui répertorie les quelques raccourcis et commandes que j'ai découverts au fil du temps et de balades sur le net (blogs, forums, wiki, man bash, etc.). J'essaie de faire une liste ici de ceux qui me semblent vraiment utiles pour l'utilisation quotidienne du terminal par un utilisateur lambda. Je fais partie de cette catégorie, je ne suis ni un programmeur, ni un utilisateur averti, je fais de la recherche en sciences humaines et sociales et de l'édition. Aujourd'hui, je n'utilise quasiment plus qu'un navigateur web et un terminal (vim, mutt, pandoc, etc.). Dans mon domaine, on voit de plus en plus de gens s'intéresser à des outils comme vim, mais ils sont rebutés par l'utilisation du terminal lui-même (avant même celle de vim). Voilà donc quelques astuces qui facilitent grandement l'utilisation d'un terminal utilisant le shell unix bash.

Des raccourcis utiles

  • Ctrl + a : Pour aller au début de la ligne
  • Ctrl + e : Pour aller à la fin de la ligne
  • Ctrl + b : Pour se déplacer d'un caractère vers l'arrière (flèche gauche)
  • Ctrl + f : Pour se déplacer d'un caractère vers l'avant (flèche droite)
  • Alt + b : Pour se déplacer d'un mot vers l'arrière
  • Alt + f : Pour se déplacer d'un mot vers l'avant
  • Ctrl + xx : Pour passer de la position du curseur au début de la ligne et revenir à la position où se trouvait le curseur

  • TAB : Pour compléter automatiquement les noms de fichiers/dossiers/commandes

  • Ctrl + d : Pour effacer le caractère sur lequel se trouve le curseur

  • Ctrl + h : Pour effacer le caractère précédant le curseur (la fonction classique du retour arrière)

  • Alt + d : Pour effacer le mot suivant le curseur

  • Alt + retour arrière : Pour effacer le mot précédant le curseur

  • Ctrl + l : Pour nettoyer l'écran (l'équivalent de la commande clear)

  • Alt + t : Pour échanger la place du mot où se trouve le curseur avec celui le précédant

  • Ctrl + t : Pour échanger la place des deux caractères précédant le curseur

  • Ctrl + w : Pour couper le mot précédant le curseur

  • Ctrl + k : Pour couper la partie de la ligne suivant le curseur

  • Ctrl + u : Pour couper la partie de la ligne précédant le curseur

  • Ctrl + y : Pour coller la dernière chose coupée

  • Ctrl + _ : Pour annuler la dernière modification (undo)

  • Ctrl + j : Pour créer une nouvelle ligne

  • Ctrl + c : Pour arrêter la commande en cours et créer aussi une nouvelle ligne

  • Ctrl + r : Pour rechercher une commande précédente dans l'historique

  • Ctrl + g : Pour quitter la recherche dans l'historique

  • Ctrl + p : Commande précédente (flèche haut)

  • Ctrl + n : Commande suivante (flèche bas)

  • Ctrl + x + e : Pour lancer un traitement de texte (nano par ex.) pour écrire une longue commande.

La dernière commande

  • !! : Pour répéter la dernière commande
    Notamment très utile quand on oublie de mettre sudo avant une commande.
    $ apt install apt (qui donne une erreur parce qu'on a oublié sudo)
    $ sudo !!

  • alt + . : Pour ajouter le dernier argument de la dernière commande
    $ vim todo.txt
    $ mv [alt + .]todo.txt ~/tmp

  • !$ : Egalement utile pour ajouter le dernier argument de la dernière commande

  • !* : Pour reproduire tous les arguments de la dernière commande
    C'est utile si vous faites une erreur du genre :
    $ vim cd ~/downloads
    $ !*
    ce qui donnera
    $ cd ~/downloads

  • !foo : Pour réutiliser la dernière commande en commençant par foo (on peut aussi faire foo !!)

  • !:- : Pour réutiliser la dernière commande sans le dernier argument
    Un exemple:
    $ ping -c 3 linuxfr.org
    $ !:- framasoft.org
    Ce qui donnera
    $ ping -c 3 framasoft.org

  • A ces commandes, vous pouvez ajouter à la fin :p (par ex. !*:p) pour afficher la commande sans qu'elle se lance.

Astuces au quotidien

  • $ cp ~/.vimrc{,.old}
    Qui correspond à
    $ cp ~/.vimrc ~/.vimrc.old
    Ca marche aussi pour supprimer une extension par ex. pour transformer "blabla.txt" en "blabla"
    $ mv blabla{.txt,}
    Ou pour utiliser l'extension markdown à la place du .txt :
    $ mv blabla{.txt,.md}

  • ..
    Qui correspond au dossier parent de celui dans lequel on se trouve. Par ex. : cd .. emmène au dossier parent de celui dans lequel on se trouve. Cela peut aussi être utile pour copier un fichier cp foo.txt ..

  • .
    Cela correspond au dossier dans lequel on se trouve. Par ex.: cp ~/downloads/foo.txt .

  • cd -
    Qui emmène au dernier dossier dans lequel on se trouvait

  • En cas de coquille, on peut corriger la commande précédente erronée ainsi:
    mvi todo.txt
    ^mvi^vim

  • Pour appliquer une action (supprimer, copier, etc.) sur de nombreux fichiers qui ont des noms similaires, on peut utiliser l'astérisque. Par ex.:
    $ ls
    Fichier1.txt
    Fichier2.txt
    Fichier3.txt
    Fichier4.txt
    $ rm Fichier* (cela supprimera tous les fichiers commençant par "Fichier")
    ou
    $ rm *.txt (cela supprimera tous les fichiers ayant l'extension ".txt")

  • Pour renommer rapidement une série de fichiers, on peut utiliser rename ainsi :
    $ ls
    Fichier1.txt
    Fichier2.txt
    Fichier3.txt
    Fichier4.txt
    $ rename 's/Fichier/texte/' *.txt
    $ ls
    texte1.txt
    texte2.txt
    texte3.txt
    texte4.txt

  • Pour changer les extensions de plusieurs fichiers (en utilisant toujours rename, il est possible d'utiliser d'autres méthodes bien évidemment, avec find par ex.) :
    rename 's/\.txt$/\.md/' *.txt

  • ls -thor
    Pour invoquer le pouvoir du marteau ! Et accessoirement lister de façon complète et lisible les fichiers d'un dossier en fonction de leur date de modification (de la plus ancienne à la plus récente). Il n'y aura pas les fichiers cachés dans la liste. Pour cela il faut invoquer les écritures saintes ls -torah.

  • Pour supprimer tous les fichiers dans un dossier sauf un type de fichier (pdf et zip par ex.)
    $ rm !(*.pdf|*.zip)

Toutdoux liste

Une commande utile (un peu dangereuse) si vous maintenez un fichier ~/faire.txt (le fameux todo.txt, que je maintiens personnellement selon une méthode "Getting things done" à ma sauce). Je maintiens aussi un fichier ~/lecture.txt (le sujet de l'exemple ci-dessous) dans lequel j'ai une liste de livres/articles à lire (utile pour mon boulot, notamment avant de me rendre à la bibliothèque).
Pour ajouter une ligne à un fichier
$ echo "- Luciano Floridi, the fourth revolution, Oxford University Press, 2014" >> ~/lecture.txt
Cela ajoute une ligne à la fin de ce fichier contenant ce qui se trouve entre guillemets (en passant cet auteur peut vous intéresser).
C'est une méthode un peu dangereuse, parce que si on ne met qu'un ">" à la place de 2 ">", on écrase le fichier.

Je peux donc lancer rapidement un terminal (j'ai un raccourci pour cela) et faire un less lecture.txt pour voir la totalité de la liste.
Je peux aussi faire un head -5 lecture.txt pour afficher les 5 premières lignes, ou les 5 dernières avec tail -5 lecture.txt.

Mais encore une fois, attention à ne pas faire $ echo "blabla" > lecture.txt ! Cela supprimera le contenu du fichier et ne laissera que "blabla".

Le partage facile d'un dossier au sein d'un réseau

Pour un partage facile d'un dossier avec une personne utilisant le même réseau, on peut lancer une commande créant un serveur depuis le dossier à partager :
python3 -m http.server
Ca fonctionne aussi avec python2 : python -m SimpleHTTPServer
Pour préciser le port il suffit d'ajouter le numéro à la fin de la commande : python3 -m http.server 8042
Et d'autres langages peuvent faire la même chose bien sûr
Avec ruby par ex.:
ruby -run -e httpd . (le port sera indiqué au lancement de la commande mais c'est possible de le préciser avec -p par ex.: ruby -run -e httpd . -p 8042)

A suivre

Je m'attarde ici sur bash, mais cela devrait fonctionner mosso grodo avec les autres shell aussi (zsh notamment). Et je vise ici les astuces qui ne nécessitent pas de modifier .bashrc. Par ex., j'utilise certaines modifications de mon .bashrc comme :

alias ll='ls -alF'
alias la='ls -A'
alias l='ls -CF'

Quelques autres idées me viennent pour de futurs journaux, si ça vous intéresse : 1) un journal sur bashrc pour rendre la vie de l'utilisateur lambda plus facile 2) un journal sur un vimrc pour "non-programmeur", qui souhaite utiliser vim comme traitement de texte principalement 3) un journal sur des scripts bash utiles au quotidien pour un utilisateur lambda 4) un journal sur une automatisation (évitant notamment le danger du ">", faisant des sauvegardes, etc.) de ma liste de tâches. Il existe de nombreux programmes "todo list", mais je n'en ai trouvé aucun qui me satisfasse entièrement.
Enfin… A suivre…

Je vous laisse aussi ajouter d'autres raccourcis, commandes et astuces qui peuvent être utiles à un utilisateur standard selon vous (s'il y a des fautes, n'hésitez pas non plus).
Cette liste n'est vraiment pas exhaustive. Elle représente ce que j'utilise le plus. Il y a de nombreux autres raccourcis et astuces sur la toile.

Bonne bidouille !

  • # Merci

    Posté par  (site web personnel) . Évalué à 4.

    Super bien !! Très bonne idée. Merci.

    J'en connaissais déjà pas mal, mais c'est cool d'en découvrir de nouveaux bien pratiques.
    Tes autres idées de journaux sont bonnes également. Je prendrais volontiers.

    Un truc qui m'intéresserait - j'ai jamais pris le temps de me pencher sur la question - c'est l'utilisation du pipe et le chainage des commandes.
    Par exemple, faire une recherche de tous les fichiers flac d'un dossier, de façon récursive et conversion de chacun en mp3. (Bon j'ai déjà résolu ce problème - en python -, mais c'est un exemple parlant du genre de bricoles que je souhaite souvent faire, et que je ne sais pas faire en bash).

    There is no spoon...

    • [^] # Re: Merci

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

      Pour la conversion flac -> mp3, la commande find me semble toute indiquée.

      La gelée de coings est une chose à ne pas avaler de travers.

      • [^] # Re: Merci

        Posté par  (site web personnel) . Évalué à 1.

        Oui oui tout à fait. C'est ce que j'avais trouvé.

        find avec -print0 et | xargs

        Mais justement, c'est ce genre de subtilités, appliquées à d'autres contextes que je souhaiterais mieux maitriser. ;)

        There is no spoon...

        • [^] # Re: Merci

          Posté par  . Évalué à 6.

          Je copie colle une petite doc personnelle qui explique un peu find grep et xargs…

          find

          Trouver tous les fichiers cpp contenu dans le repertoire courant et
          tous les sous repertoires:

          find . -name '*.cpp'

          A présent on veut filtrer la liste produite par find, pour ne trouver
          que les lignes qui contiennent un mot donné. Ce mot pourra etre soit
          dans le chemin (nom d'un repertoire) soit dans le nom du fichier (on
          fait un grep sur une liste de lignes). On va utiliser grep sur la
          liste donnée par find.

          find . -name '.cpp' -print | grep agilent
          Attention, c'est case-sensitive, du coup la commande suivante ne donne
          pas tous les fichiers.
          Pour lui dire d'ignorer la casse, option -i de grep. Ca donne:
          find . -name '
          .cpp' -print | grep -i agilent

          xargs: le pouvoir

          Plus fort encore: xargs, pour faire des choses sur les fichiers
          produits par le find. Cette fois ci on ne va pas filtrer la liste que
          sort find, mais faire un grep directement dans chaque fichier trouvé.

          Voice des exemples:

          Touver tous les fichiers cpp puis faire un grep dans chacun d'eux pour
          trouver la chaine "if ( isNarrow_ )"

          $ find . -name '*.cpp' -print | xargs grep 'if ( isNarrow_ )'
          ./comp/src/algorithm/soundextract/AgileSoundInfo.cpp: if ( isNarrow_ )
          ./comp/src/algorithm/soundextract/AgileSoundInfo.cpp: if ( isNarrow_ )

          Meme chose en affichant le numéro de ligne (option -n du grep)
          $ find . -name '*.cpp' -print | xargs grep 'if ( isNarrow_ )' -n
          ./comp/src/algorithm/soundextract/AgileSoundInfo.cpp:353: if ( isNarrow_ )
          ./comp/src/algorithm/soundextract/AgileSoundInfo.cpp:457: if ( isNarrow_ )

          On peut evidement cumuler les filtres: find | grep | xargs grep. Par
          exemple:
          dans share un
          find . -name '.cpp' -print
          trouve 15664 fichier.
          find . -name '
          .cpp' -print | grep sound
          trouve 14 fichiers. Et
          find . -name '*.cpp' -print | grep sound | xargs grep 16000
          fait un grep dans ces 14 fichiers pour ne trouver qu'un seul resultat.

          l'un OU l'autre

          Maintenant voyons comment introduire le "ou" dans le find:

          Touver tous les fichiers h OU cpp, et faire un grep sur la liste
          produite afin de ne recuperer que la liste des fichier qui contiennent
          la chaine "AgileSound"
          Ici on a besoin des parentheses pour isoler l'expression car elle est
          plus complexe. Et il faut les preceder du caracteres d'echappement
          sinon le bash fait une erreur quand il voit la prenthese.
          L'option -o veut dire "or".
          find . ( -name '.cpp' -o -name '.h' ) -print | grep AgileSound

          un peu d'aide:
          http://www.gnu.org/software/findutils/manual/html_mono/find.html#Combining-Primaries-With-Operators

          grep et fichier binaire

          Parfois grep pense qu'il a affaire à un fichier binaire:

          $ grep -i DTMF MySuperSoftware.log
          Fichier binaire MySuperSoftware.log concordant
          Ce n'est pas le cas, mais il le croit. On peux s'en sortir en lui
          précisant le type de fichier auquel il a affaire, avec
          l'option --binary-files

          $ grep --binary-files=text DTMF MySuperSoftware.log
          13-10-10 09:49:11.289 [5196] DEBUG algorithm <....\src\algo\note\SndFnd.cpp:232> end DTMF found [701416,706416]
          13-10-10 09:49:12.494 [5196] DEBUG algorithm <....\src\algo\sndnote\SndFnd.cpp:162> begin DTMF found [710704,715704]

          • [^] # Re: Merci

            Posté par  . Évalué à 5.

            $ find . -name '*.cpp' -print | xargs grep 'if ( isNarrow_ )'

            Il vaut mieux utiliser … -print0 | xargs -0 …, si par exemple tu as des espaces ou des guillemets dans tes noms de fichier.

          • [^] # Re: Merci

            Posté par  . Évalué à 1.

            Touver tous les fichiers cpp puis faire un grep dans chacun d'eux pour
            trouver la chaine "if ( isNarrow_ )"

             find . -name "*.cpp" -exec grep "if ( isNarrow_ )" {} \;

            plutôt qu'un print pour un xarg; autant attaquer directement le fichier.

            • [^] # Re: Merci

              Posté par  (site web personnel) . Évalué à 6. Dernière modification le 01 décembre 2016 à 14:40.

              plutôt qu'un print pour un xarg; autant attaquer directement le fichier.

              ça coûte pas le même prix.

              $ for i in $(seq 1 10) ; do echo coin > $i ; done   # 10 fichiers contenant "coin"
              $ strace -f -o "|grep execve" -e execve find . -type f -exec /bin/grep -s coin {} >/dev/null \;
              15273 execve("/usr/bin/find", ["find", ".", "-type", "f", "-exec", "/bin/grep", "-s", "coin", "{}", ";"], [/* 67 vars */]) = 0
              15275 execve("/bin/grep", ["/bin/grep", "-s", "coin", "./1"], [/* 67 vars */]) = 0
              15276 execve("/bin/grep", ["/bin/grep", "-s", "coin", "./7"], [/* 67 vars */]) = 0
              15277 execve("/bin/grep", ["/bin/grep", "-s", "coin", "./10"], [/* 67 vars */]) = 0
              15278 execve("/bin/grep", ["/bin/grep", "-s", "coin", "./3"], [/* 67 vars */]) = 0
              15279 execve("/bin/grep", ["/bin/grep", "-s", "coin", "./4"], [/* 67 vars */]) = 0
              15280 execve("/bin/grep", ["/bin/grep", "-s", "coin", "./2"], [/* 67 vars */]) = 0
              15281 execve("/bin/grep", ["/bin/grep", "-s", "coin", "./9"], [/* 67 vars */]) = 0
              15282 execve("/bin/grep", ["/bin/grep", "-s", "coin", "./6"], [/* 67 vars */]) = 0
              15283 execve("/bin/grep", ["/bin/grep", "-s", "coin", "./8"], [/* 67 vars */]) = 0
              15284 execve("/bin/grep", ["/bin/grep", "-s", "coin", "./5"], [/* 67 vars */]) = 0
              $ strace -f -o "|grep execve" -e execve find . -type f -exec /bin/grep -s coin {} +
              15661 execve("/usr/bin/find", ["find", ".", "-type", "f", "-exec", "/bin/grep", "-s", "coin", "{}", "+"], [/* 67 vars */]) = 0
              15663 execve("/bin/grep", ["/bin/grep", "-s", "coin", "./1", "./7", "./10", "./3", "./4", "./2", "./9", "./6", "./8", "./5"], [/* 67 vars */]) = 0
              $ strace -f -o "|grep execve" -e execve sh -c "find . -type f -print0|xargs -0 /bin/grep -sh coin"
              15393 execve("/bin/sh", ["sh", "-c", "find . -type f -print0|xargs -0 "...], [/* 67 vars */]) = 0
              15395 execve("/usr/bin/find", ["find", ".", "-type", "f", "-print0"], [/* 67 vars */] <unfinished ...>
              15396 execve("/usr/bin/xargs", ["xargs", "-0", "/bin/grep", "-sh", "coin"], [/* 67 vars */] <unfinished ...>
              15397 execve("/bin/grep", ["/bin/grep", "-sh", "coin", "./1", "./7", "./10", "./3", "./4", "./2", "./9", "./6", "./8", "./5"], [/* 67 vars */] <unfinished ...>

              donc onze processus (un find et 10 grep), deux (find, grep) ou trois (un find, un xargs et un grep) suivant les cas.

              Remarque: le nombre de grep dans le 3e cas peut augmenter suivant les limites d'xargs et du shell, mais il sera toujours largement inférieur au premier cas. Et on peut avoir des pièges comme le "|xargs tar cvf" qui est à proscrire.

              • [^] # Re: Merci

                Posté par  . Évalué à 4.

                find avec + est pas mal, mais les solutions à base de xargs/GNU parallel sont plus fines précises. Je ne sais pas trop comment se comporte find par exemple s'il a besoin de faire plus d'un seul appel est-ce qu'il va continuer à parcourir le fs pendant l'exécution ? En fait c'est même pas sûr qu'il sache passer par plusieurs appels. xargs permet de définir le nombre de lancement concurrents il peut faire (parallel aussi avec pleins d'autres trucs en plus).

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

              • [^] # Re: Merci

                Posté par  (site web personnel) . Évalué à 5.

                Pour illustrer la remarque, avec 100000 fichiers, on a 100001 processus (un find et 100k grep), 8 processus (un find et 7 grep), 9 processus (un find, un xargs et 7 grep), respectivement.

              • [^] # Re: Merci

                Posté par  . Évalué à 2.

                ça coûte pas le même prix.

                Oui, c'était plus pour illustrer l'usage de -exec plutôt que de passer par xargs.
                Ceci dit l'usage de -exec … + reste de celui qui coûtent le moins.

                Et si on reste sur le même exemple:

                /bin/grep -s coin -r /MonRepertoire/

                est encore moins couteux.

                Et on peut avoir des pièges comme le "|xargs tar cvf" qui est à proscrire.

                Surtout, cela ne fonctionne pas - ou pire, ça part en distribil - si la commande appelée ne sait pas effectuer une même action sur un jeu de fichiers… Mais le -exec … + pose aussi problème dans ce cas.

                De plus, -exec permet de placer facilement le nom de ficher dans la commande à exécuter.
                - bon, on peut le faire aussi avec xargs -I, mais c'est plus long à écrire :) -

          • [^] # Re: Merci

            Posté par  (Mastodon) . Évalué à 0.

            Touver tous les fichiers cpp puis faire un grep dans chacun d'eux pour
            trouver la chaine "if ( isNarrow_ )"

            $ find . -name '*.cpp' -print | xargs grep 'if ( isNarrow_ )'

            Moi je n'utilises pas de pipe ou xargs pour ce genre de truc, je fais juste comparer grep à un autre fichier comme /dev/null afin qu'il m'indique le nom de fichier quand ça matche :

            ça donne ça :

            $ find . -name '*.cpp' -exec grep 'if ( isNarrow_ )' {} /dev/null \;

            • [^] # Re: Merci

              Posté par  . Évalué à 5.

              afin qu'il m'indique le nom de fichier quand ça matche :

              Pour ça, il suffit d'utiliser le drapeau -l de grep.

              $ find . -name '*.cpp' -exec grep -l 'if ( isNarrow_ )' {}  +

              Du coup, on peut utiliser + plutôt que ; pour tout envoyer d'un coup à grep.

    • [^] # Le script n'rst pas toujours la bonne reponse

      Posté par  (site web personnel) . Évalué à 5.

      As tu besoin de garder en local la "copie" mp3 de tes fichiers flac ?
      Car dans la négative tu peux regarder le filesystem fuse "mp3fs" qui va s'occuper de la conversion 'en live'

      • [^] # Re: Le script n'rst pas toujours la bonne reponse

        Posté par  (site web personnel) . Évalué à 1.

        Alors là, y m'épate !

        En effet, c'est pour convertir et transférer sur un baladeur qui ne lit que le mp3 ou graver sur des cd pour la voiture.
        J'avais fait un script, mais là, c'est encore très beaucoup plus mieux !

        Le principe est excellent en plus !

        Merci beaucoup.

        There is no spoon...

        • [^] # Mon script en python pour ceux qui veulent

          Posté par  (site web personnel) . Évalué à 2.

          J'utilise la librairie mutagen pour récupérer les tags du fichier flac, ainsi que l'encodeur lame. Le reste c'est du python3 de base.
          Il s'utilise comme suit:

          ./flac2mp3.py source_dir destination_dir

          Le script parcours récursivement l'ensemble du répertoire source_dir, convertit les fichiers flac trouvés en mp3 en reprenant les tags et les stocke dans le dossier destination_dir en reproduisant l'arborescence du dossier d'origine.

          #!/usr/bin/env python3
          
          from os.path import isdir, isfile, splitext, join, normpath
          from os import walk, mknod, makedirs
          import argparse
          import subprocess
          
          from mutagen.flac import FLAC
          
          
          SUPPORTED_FILES = ["flac"]
          LAME_OPTS = "-b 128 --resample 44.1"
          
          
          def main():
              args = parser()
          
              path = args.directory[0]
              path = normpath(path) + "/"
              dest = args.destination[0]
              dest = normpath(dest) + "/"
          
              if not isdir(path):
                  return False
          
              for root, dirs, files in walk(path):
                  if files is None:
                      continue
          
                  for file in files:
                      filename, extension = splitext(file)
                      extension = extension[1:]
          
                      if extension not in SUPPORTED_FILES:
                          continue
          
                      origfile = join(root, file)
                      destpath = root.replace(path, dest, 1)
                      destfile = join(destpath, ".".join((filename, "mp3")))
          
                      if not isdir(destpath):
                          makedirs(destpath)
          
                      if isfile(destfile):
                          continue
          
                      convert(origfile, destfile)
          
          
          def parser():
              parser = argparse.ArgumentParser(description="FLAC to MP3 batch converter.")
              parser.add_argument("directory",
                                  nargs=1,
                                  help="Directory containing FLAC files to convert.")
              parser.add_argument("destination",
                                  nargs=1,
                                  help="Target directory to store MP3 files to.")
          
              return parser.parse_args()
          
          
          def convert(src, dest):
              tag = FLAC(src)
          
              title = ""
              index = ""
              year = ""
              artist = ""
              album = ""
          
              if tag.get('title') is not None:
                  title = tag.get('title')[0]
                  title = title.replace('"', '\'')
          
              if tag.get('tracknumber') is not None:
                  index = tag.get('tracknumber')[0]
          
              if tag.get('date') is not None:
                  year = tag.get('date')[0]
          
              if tag.get('artist') is not None:
                  artist = tag.get('artist')[0]
                  artist = artist.replace('"', '\'')
          
              if tag.get('album') is not None:
                  album = tag.get('album')[0]
                  album = album.replace('"', '\'')
          
          
              cmd = "flac -dc \"{flac}\" | lame {opts} \
                     --tt \"{title}\" \
                     --tn \"{index}\" \
                     --ty \"{year}\" \
                     --ta \"{artist}\" \
                     --tl \"{album}\" \
                     --add-id3v2 - \"{mp3}\"".format(flac=src,
                                                 mp3=dest,
                                                 opts=LAME_OPTS,
                                                 title=title,
                                                 index=index,
                                                 year=year,
                                                 artist=artist,
                                                 album=album)
          
              try:
                  subprocess.check_call(cmd, shell=True)
              except subprocess.CalledProcessError as e:
                  print(e)
          
          
          
          if __name__ == "__main__":
              main()

          There is no spoon...

          • [^] # Re: Mon script en python pour ceux qui veulent

            Posté par  . Évalué à 3.

            À moins que je rate quelque chose, ton script va être relativement lent.

            Une première solution simple pourrait être de remplacer ton script pour que tu l'appel en lui donnant en paramètre un nom de fichier *.flac et qu'il le traduise en *.mp3. Ensuite tu le lance avec find et xargs :

            find . -name '*.flac' -print0 | xargs -0LP 4 ./converter

            Tu commencera déjà à utiliser 4 CPU pour faire tes conversions :)

            Après si tu ne change pas tant de fichiers flac que ça, je pense qu'il est tout à fait acceptable de faire un :

            locate -0er '\.flac$' | xargs -0LP 4 ./converter

            locate sera largement plus rapide que find mais tu risque de ne pas trouver les fichiers très récents (un p'tit coup d'updatedb avant et c'est corrigé).

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

            • [^] # Re: Mon script en python pour ceux qui veulent

              Posté par  (site web personnel) . Évalué à 1.

              Je ne cherchais pas spécialement la performance, mais tes remarques sont pertinentes, merci ;).

              En quoi mon script python sera lent ? Sur le parcours d'arborescence ? Tu connaitrais un moyen d'améliorer ça (toujours en python :D) ?

              There is no spoon...

              • [^] # Re: Mon script en python pour ceux qui veulent

                Posté par  . Évalué à 5.

                Ce n'est pas ton script qui est particulièrement lent, c'est juste qu'il fait les choses très séquentiellement (il fouille le disque, il trouve un truc, il le traite, il fouille le disque,…). Là où il demande moins de travail de faire plus rapide (utiliser find ou locate à la place de code la recherche en python)

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

    • [^] # Re: Merci

      Posté par  . Évalué à 2.

      Par exemple, faire une recherche de tous les fichiers flac d'un dossier,
      de façon récursive et conversion de chacun en mp3

      Si l'outil de conversion est capable de renommer lui même le fichier de sortie de .flac et .mp3 il suffit de tout passer à exec:

      find monDossierDemusique  -name "*.flacc" -type f -exec flacToMp3 {} \;

      La dernière fois que j'ai lancé un truc comme ça, le flacToMp3 était un script shell de mon cru qui appelait le véritable convertisseur avec:

      • les bonnes options
      • un nom de fichier en sortie calculé à coup de basename et cie.
  • # noclobber

    Posté par  . Évalué à 9.

    L’option noclobber de bash empêche les redirections avec > vers des fichiers qui existent.
    Il faut alors utiliser >| pour rediriger vers le fichier.
    Le comportement de >> n'est pas modifié.

    • [^] # Re: noclobber

      Posté par  . Évalué à 3.

      Génial, merci ! Tu viens de supprimer une source d'angoisse chaque fois que j'effectue un ajout !

      Alors, si jamais pour activer noclobber :
      set -o noclobber

      Et pour l'ajouter à votre .bashrc :
      echo 'set -o noclobber' >> ~/.bashrc

      A partir de là, vous ne pourrez plus faire un echo "blabla" > ~/lecture.txt, si le fichier existe déjà. Si vous voulez l'écraser, il faudra donc faire : echo "blabla" >| ~/lecture.txt

      • [^] # Re: noclobber

        Posté par  . Évalué à 6.

        Oui, mais attention à l'effet pervers quand on arrive dans un shell où l'option n'est pas activée !

      • [^] # Re: noclobber

        Posté par  . Évalué à 10.

        tu peux aussi te définir une fonction todo dans ton .bashrc

        todo(){
          if [ "$#" -eq 0 ]
          then
            head ~/TODO
          else
            echo "$*" >> ~/TODO
          fi
        }

        todo sans paramètre t'affiche les 10 premières lignes de todo
        todo avec paramètres t'ajoute les arguments à todo :)

        Il ne faut pas décorner les boeufs avant d'avoir semé le vent

        • [^] # Re: noclobber

          Posté par  . Évalué à 2.

          pour les todo lists, il y a aussi l’excellent taskwarrior.

          task [add|edit|done|delete|...]
    • [^] # Re: noclobber

      Posté par  . Évalué à 5.

      Notez que cette fonctionnalité n'est en rien spécifique à bash puisqu'elle est standardisée POSIX, mais la façon standard de l'activer sur tous les interprètes est set -C

  • # Commentaire supprimé

    Posté par  . Évalué à 10.

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

    • [^] # Re: Kill-ring

      Posté par  (site web personnel, Mastodon) . Évalué à 6. Dernière modification le 29 novembre 2016 à 17:41.

      Elle a l'air sympa, ta grand-mère! Mais, elle utilise vraiment emacs?

      La gelée de coings est une chose à ne pas avaler de travers.

    • [^] # Re: Kill-ring

      Posté par  . Évalué à 6.

      Notez aussi que tous les outils utilisant la libreadline bénéficient des mêmes raccourcis claviers, et que le fichier pour les configurer est ~/.inputrc.

      • [^] # Re: Kill-ring

        Posté par  . Évalué à 1.

        et pour ceux qui disent que ce n'est que du emacs, on peut ajouter au début du fichier ~/.inputrc
        set editing-mode vi
        et appuyer sur échap pour sortir du mode édition et retrouver ses habitudes vim ;)

  • # .bash_aliases

    Posté par  . Évalué à 2.

    Tu peux créer un fichier .bash_aliases dans ton 'home directory' pour regrouper tes alias.
    et je te rajoute:
    alias cls='printf "\033c"'

    et le & à la fin d'une ligne de commande pour conserver l'accès au prompt.

    • [^] # Re: .bash_aliases

      Posté par  . Évalué à 4.

      Ça fait la même chose que "clear" ta commande.

      • [^] # Re: .bash_aliases

        Posté par  . Évalué à 1.

        Pas sur terminal csh en tous cas…
        clear 'remonte' le prompt en haut de la fenêtre du terminal, la commande citée ci-dessus "efface" le contenu du terminal: elle correspond à la commande cls d'un terminal DOS.

    • [^] # Re: .bash_aliases

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

      L'alias cls peut être remplacé par CTRL-L

      La gelée de coings est une chose à ne pas avaler de travers.

  • # Merci

    Posté par  . Évalué à 1.

    Merci pour ce journal, pour moi qui m'essaye aux arcanes du Bash, c'est une vraie mine d'or.

    C'est immédiatement CTRL+D dans mon navigateur.

    La majeure partie des morts l'était déjà de son vivant et le jour venu, ils n'ont pas senti la différence.

    • [^] # Re: Merci

      Posté par  . Évalué à 3.

      CTRL+D permet aussi de quitter le shell si le prompt est vite ;-)

    • [^] # Re: Merci

      Posté par  (Mastodon) . Évalué à 3.

      C'est immédiatement CTRL+D dans mon navigateur.

      Ah, dans le navigateur, ça fonctionne bien ? Parce que chaque fois que j'ai tenté ^D dans un shell, immédiatement mon clavier se blo

  • # Ma contribution

    Posté par  . Évalué à 5.

    Ctrl-x * : permet d'étendre le pattern qui précède.
    C'est très pratique pour vérifier une commande avant de l'exécuter.

    Par exemple, dans votre $HOME tapez

    echo .bash*

    puis Ctrl-x * pour obtenir quelque chose comme

    echo .bash_history .bash_profile .bashrc

    Ctrl-x g : Idem mais affiche sans remplacer.

    Certaines des commandes mentionnées dans l'article sont obtenues de façons plus intuitives avec les flêches.

    Par example, Alt-f et Alt-b peuvent être remplacés par Ctrl-Right et Ctrl-Left.

    Si cela ne fonctionne pas, cela indique problablement que readline n'est pas correctlement configuré. La configuration par défaut se trouve en général dans /etc/inputrc mais il est possible de se faire sa propre configuration dans ~/.inputrc

    Par exemple, mon terminal génère les séquences [[1;3D et [[1;3C pour Alt-Left et Alt-Right.

    Rappel: Utilisez 'cat' pour visualiser les séquences correspondant à chaque touche. [ correspond à \e, le caractère d'échappement

    Je peux les associer aux actions end-of-line et beginning-of-line (comme Ctrl-a et Ctrl-e) avec le fichier ~/.inputrc suivant:

    $include /etc/inputrc
    $if mode=emacs
    "\e[1;3C": end-of-line
    "\e[1;3D": beginning-of-line
    $endif

    Le même principe est applicable à toutes les touches du clavier (y compris les Fn).

    Pour plus d'informations, voir man 3 readline

  • # Un petit alias de rien du tout

    Posté par  . Évalué à 2.

    Juste un petit alias tout bête pour compléter ceux qui sont donnés, et que j'utilise souvent:
    alias lt='ls -lhtr'

    Ce qui nous fait un petit ls détaillé en classant les fichiers par date, en indiquant les plus récents en dernier. Pratique pour repérer en un clin d’œil les derniers fichiers d'un dossier fouillis :)

  • # Prompt bash sur 2 lignes.

    Posté par  . Évalué à 1.

    Voici le prompt bash sur 2 lignes que j'utilise depuis quelques années
    Je trouve très pratique de séparer les informations et la commande.

    Il utilise le mode 256 couleurs qui doit maintenant fonctionner à peu près partout (sauf dans la console linux). Il rend mieux sur un terminal de couleur sombre.

    Les variables PROMPT_MODE, PROMPT_MODE_COLOR et PROMPT_COLOR peuvent être modifiées dynamiquement.

    La fonction show256colors affiche les 256 couleurs disponibles (pour PROMPT_MODE_COLOR et PROMPT_COLOR )

    PROMPT_MODE="none"    # Un texte arbitraire inséré dans le prompt
    PROMPT_MODE_COLOR=36  # La couleur de ce texte (0-255)
    PROMPT_COLOR=46       # La couleur de la barre de gauche
    
    function set-prompt () {
       # reminder: xterm escape sequences must be encapsulated within \[ \].
       #           This is needed by bash to compute the 'visible' length of 
       #           the prompt 
       local col0="\[\e[0m\]"     # reset 
       local col1="\[\e[1;31m\]"  # pwd color 
       local col2="\[\e[48;5;${PROMPT_COLOR}m\]"  # left margin color
       local col3="\[\e[1;33m\]"  # [user@host] color
       local col4="\[\e[38;5;${PROMPT_MODE_COLOR}m\]"  # color of $PROMPT_MODE 
       PS1="\n$col2 $col0 $col3[\u@\h] $col4$PROMPT_MODE${PROMPT_MODE:+ }$col0$col1\w$col0 \n$col2 $col0 "
    }
    
    PROMPT_COMMAND=set-prompt
    
    function show256colors () {
        for ((i=0;i<16;i++)) ; do 
            for ((j=0;j<16;j++)) ; do 
                COL=$((i*16+j)) ; 
                printf "$(tput setaf $COL)%3d$(tput sgr0) $(tput setab $COL)%3d$(tput sgr0) " $COL $COL ; 
            done  
            echo  
        done
    }
  • # et "?" ?

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

    On peut utiliser le ? comme joker, il remplace tout caractère non vide
    $ ls
    fichier1.txt
    fichier20.txt
    fichier2a.txt
    fichier2.txt

    Pour ne supprimer que fichier20.txt et fichier2a.txt
    $ rm -v fichier2?.txt
    'fichier20.txt' supprimé
    'fichier2a.txt' supprimé

    • [^] # Re: et "?" ?

      Posté par  . Évalué à 6.

      Il y a aussi les crochets si tu veux n'accepter qu'un sous-ensemble des caractères possibles, en pouvant spécifier des intervalles.
      Exemple:

      $ rm fichier[1-79].txt

      supprimera fichier1.txt, fichier5.txt mais pas fichier8.txt

      Et les accolades qui permettent de générer du texte (alternatives ou séquences), indépendamment des fichiers.

      $ echo "c'est le "{matin,soir}
      c'est le matin c'est le soir
      $ echo {1..15}
      1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
      $ echo {000..200..40}
      000 040 080 120 160 200

      et on peut les imbriquer

      echo "version "{1.{1..5},2.{4,5},3.7}
      version 1.1 version 1.2 version 1.3 version 1.4 version 1.5 version 2.4 version 2.5 version 3.7
  • # histverify

    Posté par  . Évalué à 1.

    Pour les !!, !$, !!* et autres, je ne connaissais pas :p, mais il y a une alternative : shopt -s histverify. Avec ça, au lieu d'exécuter la commande directement quand on valide, ça remplace le symbole et permet de modifier si besoin avant de valider.

    Et pour ceux qui utilisent Zsh : setopt hist_verify :-)
    (Il y a probablement une option dans Zsh pour que Tab remplace !! et autres car c'est le comportement que j'ai avec zsh, mais je ne trouve pas d'option qui corresponde dans mon zshrc…)

    • [^] # Re: histverify

      Posté par  . Évalué à 3.

      Avec zsh, on peut tout simplement faire "tab" pour évaluer les expressions "!", ce qui est bien plus pratique qu'avec bash.

  • # bypasser un alias

    Posté par  . Évalué à 5.

    j'ai l'alias suivant: (rm avec garde fous)
    [cmic@zombie ~]$ alias rm='rm -i'

    Mais parfois, je suis sûr de moi, ou bien je n'ai pas envie de répondre aux prompts:
    [cmic@zombie ~]$ \rm *

    cmic

    • [^] # Re: bypasser un alias

      Posté par  . Évalué à 2.

      Merci pour celui là…. ça va me sauver sur certain grep

    • [^] # Re: bypasser un alias

      Posté par  (site web personnel) . Évalué à 5.

      Pour le rm, j'utilise l'alias:

      alias rm='sleep 2;rm'
      Mine de rien, 2 secondes de latence, ça peut être utile…

      Pourquoi bloquer la publicité et les traqueurs : https://greboca.com/Pourquoi-bloquer-la-publicite-et-les-traqueurs.html

      • [^] # Re: bypasser un alias

        Posté par  . Évalué à 6.

        Et moi :

        alias rm='shred -fuzn 15'

        Parce que bon les sécurités c'est pour les autres.

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

    • [^] # Re: bypasser un alias

      Posté par  (site web personnel) . Évalué à 2.

      J'ai aussi cet alias bien pratique, j'ai même rajouté ses cousins:

      alias cp='cp -i'
      alias mv='mv -i'
      

      et si tu veux "forcer" sans avoir le prompt (bien pratique quand tu rm plein de fichiers), tu peux y aller à coups de rm -f.

  • # Ma config de bash

    Posté par  . Évalué à 6.

    Je n'utilise bash que sous la contrainte, mais dans ce genre de cas j'apporte les options suivantes :

    • autocd : permet de se déplacer en indiquant le dossier sans cd ($OLDPWD équivaut alors à cd -)
    • globstar : permet d'avoir des globbings plus évolués comme le fameux ** pour être récursif (mv ~/**/*.pdf /dest/)
    • histappend : améliore la gestion de l'historique quand on a plusieurs shell de lancé (c'est pas parfait, mais c'est moins pire que ce qui est fait de base)

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

    • [^] # Re: Ma config de bash

      Posté par  . Évalué à 7. Dernière modification le 30 novembre 2016 à 13:35.

      export HISTSIZE=-1
      export HISTFILESIZE=-1
      export HISTCONTROL=ignoreboth
      export HISTFILE=~/.bash_history
      

      Ça permet d'avoir un historique partagé entre les différentes sessions bash ouvertes. L'historique est mis à jour (écrit et lu) à chaque commande entrée et sa taille n'est pas limitée.

      De plus, les commandes précédées d'un espace ne sont pas sauvée dans l'historique. Pratique quand on ne veut pas avoir rm -rf *, mplayer video_embarassante.mkv ou telnet -l root cia.gov dans son historique.

      • [^] # Re: Ma config de bash

        Posté par  . Évalué à 3.

        export HISTSIZE=-1
        export HISTFILESIZE=-1
        export HISTCONTROL=ignoreboth
        export HISTFILE="~/.bash_history"

        Ça permet d'avoir un historique partagé entre les différentes sessions bash ouvertes. L'historique est mis à jour (écrit et lu) à chaque commande entrée et sa taille n'est pas limitée.

        Je ne connaissais pas, merci :)

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

      • [^] # Re: Ma config de bash

        Posté par  . Évalué à 2.

        export HISTCONTROL=ignoredups

        Ça permet de ne pas dupliquer dans l'historique les commandes.

  • # Gestion de fichier en ligne de commande

    Posté par  . Évalué à 6.

    $ echo "blabla" > lecture.txt

    Si tu veux éviter ça, et même d'une manière générale pour te simplifier la vie, autant faire un alias par exemple

        lecture_ajout "Comme un poisson dans l'herbe"

    pour ajouter cet ouvrage à ta liste.

    Tu peux faire aussi

        # pour lire le fichier avec less (depuis n'importe quel répertoire)
        lecture
        # pour faire un grep dans le fichier
        lecture_cherche

    De la même manière, j'enregistre mes numéros de téléphone dans un fichier texte et j'ai un alias

        geekophone "chaîne de caractères"

    pour greper dans le fichier un motif (portion de nom, de numéro).

    Je mets aussi les surnoms dans la ligne. Et pour faire des groupes, il suffit de mettre une étiquette sur la ligne d'un numéro :

        John Smith Hannibal    06 456 6575 214    A-TEAM
        Templeton Peck Face    06 454 5346 574    A-TEAM

    Avec un nombre raisonnable de numéros, il suffit de très peu de caractères pour trouver celui qu'on veut donc c'est super rapide à consulter.

  • # zsh: vi mode !

    Posté par  (site web personnel) . Évalué à 4.

    De mon côté, j'ai récemment découvert que ZLE (l'éditeur de ligne de zsh), avait un mode vi: en appuyant sur echap je peux éditer mes lignes de commande comme si j'étais dans vim. C'est très pratique, et du coup je n'utilise plus aucun raccourci clavier pour me déplacer ou éditer, mais j'appuie sur echap :)

    • [^] # Re: zsh: vi mode !

      Posté par  . Évalué à 3.

      J'ai essayé plusieurs fois, mais j'ai toujours eu du mal avec ce mode (qu'il est aussi possible d'avoir avec bash et la readline : set -o vi).

      Je pense que ça m'aiderait d'avoir une visuel du mode dans le quel je suis.

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

      • [^] # Re: zsh: vi mode !

        Posté par  . Évalué à 4.

        Cela contribuerait-il à ton bonheur (pour Bash) ?

        Variables de readline
               Readline  dispose  de variables permettant de personnaliser encore plus
               son comportement. Une variable peut être  configurée  dans  le  fichier
               inputrc avec une affectation de la forme
        
                      set nom_de_variable valeur

        […]

        show-mode-in-prompt (Off)
                      Si  configurée  à  On,  ajoute un caractère au début de l’invite
                      indiquant le mode d’édition : Emacs  (@),  commande  Vi  (:)  ou
                      insertion Vi (+).
      • [^] # Re: zsh: vi mode !

        Posté par  (site web personnel) . Évalué à 4.

        Et pour ZSH:

        function zle-line-init zle-keymap-select {
            RPS1="${${KEYMAP/vicmd/-- NORMAL --}/(main|viins)/-- INSERT --}"
            RPS2=$RPS1
            zle reset-prompt
        }
        
        zle -N zle-line-init
        zle -N zle-keymap-select
        

Suivre le flux des commentaires

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