Exile on Keyboard St. - Blog sur Linux et Debian

Aller au contenu | Aller au menu | Aller à la recherche

dimanche 15 avril 2018

Rechercher rapidement dans le code source avec ack

Rechercher dans du code source est une des activités principales du développeur.

Dans les logiciels aux architectures incertaines et maintenant avec la "méthode" Agile, il est souvent diffcile de savoir rapidement ou est gérée telle ou telle fonctionnalité dans le code.

Pendant longtemps, rechecher dans le code ressemblait à ça:

find . -name "*.java" -exec grep HashMap {} \; -print

Certains me diront:

Bahhhhh, Qu'est-ce que c'est compliqué ?

Où encore l'excuse qui n'en est pas une:

Mais moi je suis sous Windows ...

Heureusement, il existe maintenant des outils plus rapides à l'usage que les commandes find et grep combinées.

J'ai découvert il y a quelques années la commande ack-grep ou ack qui est précisément faites pour notre besoin: chercher des motifs dans une base de code.

Je vous passe ici l'installation d'ack: ack est un script Perl qui s'installe très simplement ; évitez le package de votre distribution afin d'avoir la version la plus récente.

Maintenant, notre commande précédente s'écrit comme suit:

ack --java HashMap

C'est quand même plus court !

J'ai précisé à la commande que je voulais chercher dans des sources Java. Dans types de fichiers sont prédéfinis dans ack:

 ack --help-types
Usage: ack [OPTION]... PATTERN [FILES OR DIRECTORIES]

The following is the list of filetypes supported by ack.  You can
specify a file type with the --type=TYPE format, or the --TYPE
format.  For example, both --type=perl and --perl work.

Note that some extensions may appear in multiple types.  For example,
.pod files are both Perl and Parrot.

    --[no]actionscript .as .mxml
    --[no]ada          .ada .adb .ads
    --[no]asm          .asm .s
    --[no]asp          .asp
    --[no]aspx         .master .ascx .asmx .aspx .svc
    --[no]batch        .bat .cmd
    --[no]cc           .c .h .xs
    --[no]cfmx         .cfc .cfm .cfml
    --[no]clojure      .clj
    --[no]cmake        CMakeLists.txt; .cmake

Si vous utilisez un type de fichier non connu d'ack, vous pouvez le définir.

Ensuite, de nombreuses options de la commandes ack sont reprises de celles de grep:

       -i, --ignore-case
           Ignore case distinctions in PATTERN
       -v, --invert-match
           Invert match: select non-matching lines

ou les classiques:

       -l, --files-with-matches
           Only print the filenames of matching files, instead of the matching text.

       -L, --files-without-matches
           Only print the filenames of files that do NOT match.

ack permet comme grep d'afficher les lignes de contexte autour du motif trouvé:

       -A NUM, --after-context=NUM
           Print NUM lines of trailing context after matching lines.

       -B NUM, --before-context=NUM
           Print NUM lines of leading context before matching lines.

ce qui facilite la lisibilité de la sortie.

Par défaut, ack va parcourir tous les sous-répertoires du répertoire courant. Ce comportement peut-être changé par:

       -r, -R, --recurse
           Recurse into sub-directories. This is the default and just here for compatibility with grep. You can also use it for
           turning --no-recurse off.

Enfin, ack peut utiliser un fichier de configuration ~/.ackrc.

Pour créer celui utilisant les options par défaut:

ack --create-ackrc > ~/.ackrc

dimanche 5 octobre 2014

La commande find sous Linux: le couteau suisse du développeur !

La commande find du paquet findutils est probablement la plus utilisée par les développeurs et les administrateurs Linux avec évidemment ls, cd et grep.

Sa syntaxe étant parfois déroutante, il n'est pas inutile de passer quelques minutes à recenser les différentes utilisations de cette commande.

Si on fait abstraction des options de la commande find, sa syntaxe est la suivante:

find [path ...] [expression]

Par exemple:

find

listera purement et simplement les fichiers et répertoires du répertoire courant.

find /bin

listera les fichiers et répertoires du répertoire /bin.

Si maintenant, je cherche les fichiers ayant l'extension .sh du répertoire /etc/init.d, j'utiliserai:

find /etc/init.d/ -name "*.sh"
/etc/init.d/mountdevsubfs.sh
/etc/init.d/mountall-bootclean.sh
/etc/init.d/mountall.sh
/etc/init.d/mtab.sh
/etc/init.d/mountnfs.sh
/etc/init.d/hostname.sh
/etc/init.d/checkfs.sh
/etc/init.d/bootmisc.sh
/etc/init.d/checkroot-bootclean.sh
/etc/init.d/hwclock.sh
/etc/init.d/checkroot.sh
/etc/init.d/mountnfs-bootclean.sh
/etc/init.d/umountnfs.sh
/etc/init.d/mountkernfs.sh

Notez les double-quotes ou guillements (on aurait pu aussi utiliser des simples quotes) autour de la pattern de recherche pour que le Shell ne l'interprête pas lui même. Sinon l'existence de fichiers .sh dans le répertoire courant aurait provoqué l'erreur suivante:

user@machine:~$ find /etc/init.d/ -name *.sh
find: paths must precede expression:
Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression]

Dans les exemples précédents, nous avons utilisé le flag -name. Dans la terminologie de la commande find, cela s'appele un "test". Quand le test est vrai, find renvoie le nom du fichier.

On peut aussi utiliser plusieurs tests, c'est à dire restreindre les critères de recherche:

find /etc -type d -name "rc*"

Renvoie uniquement les répertoires du répertoire /etc dont le nom commence par rc.

Si je cherche les fichiers de log non accédés depuis plus d'un an:

find /var/log/ -atime +365 -type f

find propose de nombreux autres tests pour filtrer la recherche sur la taille, l'utilisateur, le groupe, la date de modification, les permissions, ... du fichier.

Pour l'instant, nous avons montré des utilisations très simples de la commande find avec un répertoire de recherche et quelques exemples de tests. Dans un prochain billet, on détaillera les actions de find qui permettent d'éxécuter des commandes sur les fichiers trouvés, et notamment l'action -exec.

En fait, dans les commandes précédentes nous avons déjà utilisé une action sans le savoir, l'action -print qui affiche les fichiers ou répertoires trouvés, et qui est implicite en l'absence d'autre action.