Forum Programmation.shell niveau de recherche dans répertoire - reference croisé

Posté par .
Tags : aucun
1
17
fév.
2009
Bjr,

je viens de faire une belle commande shell du type

grep nouvelle1 **/**/**/**/* > log

elle me permet de chercher et lister les fichiers qui ont comme chaine de caractères nouvelle1.

la seule chose qui me gêne est le niveau de recherche dans les répertoires.

suis je obligé de faire des **/**/**/**/* et donc de connaitre le niveau de mon arborescence au préalable.

existe t il un moyen d'optimiser la chose ?
  • # si j'étais méchant

    Posté par . Évalué à 8.

    je dirais RTFM

    comme je suis gentil je te dis
    grep -R ton_truc_a_chercher /ton_rep
    -R = recursive : va chercher dans tous les sous répertoire, et ce récursivement ;)
    • [^] # Re: si j'étais méchant

      Posté par . Évalué à 2.

      j'aurais proposer un truc à base de find et de xargs, mais grep -R correspond bien à la demande énoncée
      • [^] # Re: si j'étais méchant

        Posté par . Évalué à 1.

        Propose tjrs
        • [^] # Re: si j'étais méchant

          Posté par . Évalué à 3.

          ben comme dit dans les precedents post ou tu voulais chercher/remplacer des chaines de caracteres dans une sous arborescence...

          on va commencer à utiliser les notations que l'on trouve dans les pages de manuels
          veux dire que c'est un champ obligatoire
          [xxxx] veut dire que c'est un champ optionnel


          find <dossier_de_depart> -type f [-iname ] | xargs -l1 grep -


          avec cela tu va chercher dans "dossier_de_depart"
          tous les fichiers (-type f)
          qui se nomment selon motifA (-iname motifA), pour par exemple ne chercher que les fichiers .c, .h .dat, .csv et pas tous les fichiers

          puis ca va envoyer le resultat à xargs
          qui va prendre les resultats de find 1 par 1 (-l1)
          le passer à grep qui va filter avec le motifB

          pour plus d'info sur ces 3 commandes
          man find
          man xargs
          man grep
          • [^] # Re: si j'étais méchant

            Posté par . Évalué à 3.

            y a des balises qui sont pas passées :(

            < xxx > signifie que c'est une option obligatoire

            find <dossier_de_depart> -type f [-iname < motifA > ] | xargs -l1 grep < motifB > -
            • [^] # Re: si j'étais méchant

              Posté par . Évalué à 1.

              Cela marche bien mais comment tu fais pour récupérer le resultat ds un fichier.

              J'essaie cela mais il boucle en continu

              find . -type f -print | xargs grep -R nouvelle > log
              • [^] # Re: si j'étais méchant

                Posté par . Évalué à 3.

                1°) vire le -R , tu passe les fichier en absolue, il en a pas besoin
                2°) pas besoin de préciser le "." : si tu ne met aucun répertoire, il prend le répertoire courant par défaut.
                3°) utilise -print0 (find) et -0 (xargs) : cela permet de passer n'importe quel nom de fichier

                exemple

                find -type f -print0 | xargs -0 grep nouvelle >log
          • [^] # Re: si j'étais méchant

            Posté par . Évalué à 3.

            Y a-t-il une raison pour préférer l'usage de `| xargs` plutôt que l'option -exec de find :
            find <dossier_de_départ> -exec grep <motif> {} +
            Il ne semble même pas utile de préciser le type, puisque -exec ne s'applique qu'au fichier normaux
            ...
            ?
            • [^] # Re: si j'étais méchant

              Posté par . Évalué à 2.

              je ne sais plus pourquoi j'utilises xargs (surement un vieux reflexe)

              peut-etre que le find -exec ne fonctionne pas avec les noms de fichier contenant des espaces
              ou qu'il n'affiche pas (dans notre cas) le nom du fichier contenant le motif rechercher

              il doit y avoir un raison, mais desormais je tacherais d'utiliser l'option -exec
              ;)
              • [^] # Re: si j'étais méchant

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

                C'est surtout que le passage par xargs ne lance qu'un seul processus grep, contre un nouveau processus par fichier à tester en utilisant -exec. C'est donc tout simplement une question d'optimisation.
                • [^] # Re: si j'étais méchant

                  Posté par . Évalué à -1.

                  Cela evite de boucler non.
                • [^] # Re: si j'étais méchant

                  Posté par . Évalué à 4.

                  nope, pas en utilisant le '+' à la fin de l'option -exec

                  cela dit, j'utilise systèmatiquement la version xargs, parce que :
                  - portabilité entre les unix (et oui, le find Solaris 9 est bien tout pourrave)
                  - pas envie d'apprendre des options spécifiques de find quand des commandes usuelles de shell, plus flexibles, permettent de faire la même chose.

                  Je militerais presque pour qu'on enlève des options de find ... pour revenir aux sources d'unix : faire une seule chose et le faire bien.
                  • [^] # Re: si j'étais méchant

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

                    Merci pour me l'avoir fait découvrir, je ne connaissais pas ;-)
                    -exec command {} +
                    This variant of the -exec action runs the specified command on the selected files, but the command
                    line is built by appending each selected file name at the end; the total number of invocations of
                    the command will be much less than the number of matched files. The command line is built in much
                    the same way that xargs builds its command lines. Only one instance of ‘{}' is allowed within the
                    command. The command is executed in the starting directory.
                    • [^] # Re: si j'étais méchant

                      Posté par . Évalué à 2.

                      je me souviens aussi du pourquoi je passe par xarg...

                      simplement parce que faire un grep sur un grand nombre de fichier des fois ca passe pas
                      (limite du nombre d'argumet sur la ligne de commande)

                      aussi avec xargs -l1 il prend les parametres 1 par 1
    • [^] # Re: si j'étais méchant

      Posté par . Évalué à 1.

      Merci pour ta mechanceté
  • # Structure differente

    Posté par . Évalué à 1.

    Je suis parti sur un script de ce type ou $1 est mon repertoire de travail et $2 mon fichier ou se trouve mes chaines de caractères à rechercher.

    Le tout étant reinjecter dans un fichier de trace log.

    Mais le truc c'est que je ne comprends pas pourquoi il boucle en continu.
    Dés que je mets *.csv cela marche mais des que je veux tester tous les fichiers ds mon rep Linux il boucle en continu.


    #!/bin/bash
    while read x
    do
    find $1 -type f -exec grep -R $x * > log {} \;
    done < $2
    • [^] # Re: Structure differente

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

      Oula faut pas tout mélanger.

      Soit tu utilise find afin de trouver tous les fichiers qui sont contenu dans un dossier et tu applique un grep classique au resultat :

      find $1 -type f -exec grep $x {} > log \;

      (Le {} est remplacé a chaque itération par le resultat du find il faut faire attention à où tu le met)

      Soit tu utilise grep -R qui va tout seul fouiller ton dossier et rechercher dans les fichiers qu'il aura trouver.

      grep -R $x $1

      Premier cas : on cherche tous les fichiers et on applique un grep simple sur chacun d'eux
      Deuxième cas : on applique un grep recursif sur le dossier qui va chercher les fichiers tout seul.
      • [^] # Re: Structure differente

        Posté par . Évalué à 1.

        Voila ma solution

        fichier script.sh

        #!/bin/bash
        while read x
        do
        find . -type f -print | xargs grep $x > log
        done < $1

        fichier load.sh

        #!/bin/bash
        sh script_rc.sh ref_rc

        Qu'en pensez-vous ?
        • [^] # Re: Structure differente

          Posté par . Évalué à 3.

          Il existe l'option -f pour spécifier une liste de motifs, à remplacer par -F si tu veux qu'ils soient considérés comme des chaînes fixes et non des expressions régulières. Tout cela est décrit en détails dans la man page, austère mais riche ! Par contre, je ne me souviens plus si c'est commun à tous les UNIX ou si c'est une extension de GNU, comme l'est -R.

          Moralité :

          $ grep -R -f FichierDeMotifs RépertoireÀExplorer > log

          Et ça repart ! :-)

Suivre le flux des commentaires

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