Ls, find, grep et ses amis

[size=150]Exemple N° 1[/size]
J’ai un répertoire avec 100000 fichiers dedans :open_mouth:

luciole:/home/bej/temp# ls | wc -l 100004 luciole:/home/bej/temp#
Oui, bon je sais, j’ai exagéré, mais c’est pour l’exemple. :wink:

Le problème:
Je voudrais rechercher un mot ou une chaîne de caractères dans un ou plusieurs fichiers qui se trouvent dans ce répertoire.
J’essaye:

luciole:/home/bej/temp# grep toto * bash: /bin/grep: Liste d'arguments trop longue luciole:/home/bej/temp#
Impossible de faire directement un grep sur un aussi grand nombre de fichiers.
Solution:
“Piper” ls avec xargs:

luciole:/home/bej/temp# ls | xargs grep toto fic597:toto fic598:toto luciole:/home/bej/temp#

[size=150]Exemple N° 2[/size]
Comment chercher des fichiers avec find et appliquer une commande sur le résultat trouvé.

Le problème:
Je dois retrouver tous les fichiers qui contiennent le mot “toto”. Je ne sais pas du tout oû se trouvent ces fichiers.

Solution 1:
Attention, la machine va mouliner un max. pendant pas mal de temps …

Cette commande:

  1. recherche tous les fichiers de type “regular file” (voir la man page de find)
  2. Exécute la commande grep sur le fichier trouvé avec le paramètre “toto”
  3. les accolades {} servent à stocker le nom du fichier trouvé
    C’est super efficace mais ce n’est pas la seule technique…
    On peut très bien appliquer d’autres opérations qu’un grep sur les fichiers trouvés, par exemple mv, cp ou encore rm, bref…

[size=150]Exemple N° 3[/size]
Il arrive que nos “chers utilisateurs” se croient sous windows :imp: et se permettent n’importe quoi quand aux noms de répertoires.
Par exemple un nom de répertoire … sans nom ! ou avec des caractères non imprimables…
Comment renommer ce répertoire ?
Solution:
On affiche le numéro d’inode du répertoire concerné

et ensuite on fait un find sur ce numéro d’inode pour ensuite le renommer:

j’ai trouvé par hasard un super exemple concret qui illustre tout ceci:

l’équivalent de killall httpd:

ps uax | grep httpd | grep -v grep | awk ‘{print $2}’ | xargs kill -9

  • ps uax renvoie la liste de tous les processus actifs
  • grep httpd extrait uniquement les lignes contenant httpd
  • grep -v écarte les lignes contenant des commande grep
  • awk ‘{print $2}’ affiche le second champ de la liste qui en résulte, à savoir le PID du processus
  • xargs kill -9 transmet chaque valeur à la commande kill -9, via la commande xargs

Des fois on fait un grep d’une chaîne de caractères sur le contenu entier d’un répertoire. Bien sûr, quand il y a des binaires dans ce répertoire, ca pose des problèmes: l’output du grep peut vite devenir illisible.
Une manière de ne “grepper” ( ca existe le verbe grepper ? :open_mouth: ) que les fichiers textes:

Explication:

  • La commande file * affiche le type de chaque fichier
  • La commande "egrep reprend la sortie de la commande "file * et ne retourne que les fichier de type texte.
  • La commande awk … affiche le nom de fichier du type de fichier filtré par egrep
  • Et enfin, la commande “grep” effectue la recherche voulue dans les fichiers affichés par awk.

Exemple:

bej@sandwich # grep JavaSound `file * | egrep 'script|text' | awk -F: '{print $1}'` jmf.log: connects to: com.sun.media.renderer.audio.JavaSoundRenderer@bdab91 jmf.log:!! JavaSound: No rate control numfic.txt: 20 connects to: com.sun.media.renderer.audio.JavaSoundRenderer@bdab91 numfic.txt: 24 !! JavaSound: No rate control bej@sandwich #

Pour rechercher une chaîne de caractères dans un fichier binaire, il vaut mieux utiliser la commande strings