Contenu | Rechercher | Menus

Annonce

La nouvelle clé USB Ubuntu-fr est en prévente
Rendez-vous sur la boutique En Vente Libre

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 07/09/2019, à 11:46

ar barzh paour

[Résolu] recherche dans fichier

bonjour à tous
je cherche un script qui puisse me donner le résultat suivant:
trouver les fichiers d'un répertoire (et sous répertoire)
dont une ligne contient "texte1" et dont une ligne contient "texte2"

le résultat  devrait être sous la forme
nom du fichier
N°ligne et contenu de la ligne contenant "texte1"
N°ligne et contenu de la ligne contenant "texte2

pour texte1 j'y arrive presque .... avec quelques bogues

2>/dev/null find  "$rep_rech" -depth -type f -name "*"  -exec grep -n texte1 {} \;

Dernière modification par ar barzh paour (Le 10/09/2019, à 09:24)


Ubuntu 18.04 (sept 2018) (était en essai depuis 12/2017)
Ubuntu 16.04 (07/2016) et diverses versions  Ubuntu 14.04 ,  Studio 14.04 LTS 64 bits , MATE 16.04
PC          : Intel(R) Pentium(R) CPU G4600 @ 3.60GHz  + 4GiB RAM DDR4-2400
Portable : Intel(R) Core(TM)2  Duo CPU     T5750  @ 2.00GHz 3Go de RAM DDR2 667 Mhz Ubuntu 18.04

Hors ligne

#2 Le 07/09/2019, à 13:21

MicP

Re : [Résolu] recherche dans fichier

Bonjour

Peut-être avec awk :

find "$rep_rech" -depth -type f -name "*" -exec sh -c 'awk "/texte1|texte2/ {print FILENAME \" => Ligne N°\" NR \" => \" $ $0}" "{}"' \; 2>/dev/null

Dernière modification par MicP (Le 07/09/2019, à 13:27)

Hors ligne

#3 Le 07/09/2019, à 13:30

Watael

Re : [Résolu] recherche dans fichier

soit, mais pourquoi sh -c ?


eval, c'est mal.

Hors ligne

#4 Le 07/09/2019, à 14:33

MicP

Re : [Résolu] recherche dans fichier

Oui, effectivement,
c'est suite à des essais successifs que ce sh -c a fini par rester là

find "$rep_rech" -depth -type f -name "*" -exec awk "/texte1|texte2/ {print FILENAME \" => Ligne N°\" NR \" => \" $ $0}" "{}" \; 2>/dev/null

J'ai encore beaucoup à apprendre, et parfois (souvent ces jours-ci)
je manque de méthode.

Dernière modification par MicP (Le 07/09/2019, à 14:35)

Hors ligne

#5 Le 07/09/2019, à 15:40

jamesbad000

Re : [Résolu] recherche dans fichier

Bonjour,

grep -E -nr "texte1|texte2" "$rep_rech"

Plus simple et donne un résultat plus lisible. Mais ni cette forme ni la précédente me semble-t-il, ne s'assure que les 2 sont présents dans le fichier...


L'espace et le temps sont les modes par lesquels nous pensons, et non les conditions dans lesquelles nous vivons. (Signé Albert)

Hors ligne

#6 Le 07/09/2019, à 16:20

Watael

Re : [Résolu] recherche dans fichier

texte1|texte2

c'est texte1 OU texte2.

ar barzh paour veut texte1 ET texte2.

d'ailleurs, strictement dans cet ordre ? ou texte2 peut-il indiférement apparaître après ou avant texte1 ?


eval, c'est mal.

Hors ligne

#7 Le 07/09/2019, à 17:36

pingouinux

Re : [Résolu] recherche dans fichier

Bonjour,
Avec un script en python :

$ cat mongrep.py
#!/usr/bin/python3
import sys
txt1, txt2, fic = sys.argv[1:]

with open(fic,'r') as f:
   t1=t2=False; n=0; s=''
   for lig in f:
      n+=1
      ligne=''
      if lig.find(txt1)>-1: t1=True; ligne="%5d:%s"%(n,lig)
      if lig.find(txt2)>-1: t2=True; ligne="%5d:%s"%(n,lig)
      s+=ligne
   if t1 and t2: print("%s\n%s"%(fic,s))

À utiliser ainsi :

find "$rep_rech" -type f -exec /chemin_du_script/mongrep.py "texte1" "texte2" {} \; 2>/dev/null

Hors ligne

#8 Le 07/09/2019, à 21:10

kamaris

Re : [Résolu] recherche dans fichier

Une possibilité avec grep, en stockant tout d'abord la liste des fichiers matchant texte1 et texte2 :

mapfile -td '' fichiers < <(grep -rlZ 'texte1' "$rep_rech" | xargs -0 grep -lZ 'texte2')

puis en affichant les occurrences de texte1 et texte2 avec numéro et contenu de ligne, sous la forme « chemin_fichier:numéro_ligne:contenu_ligne » :

grep -nHE 'texte1|texte2' "${fichiers[@]}"

Le stockage intermédiaire n'est pas forcément nécessaire, mais ça sépare et clarifie un peu les choses.

Hors ligne

#9 Le 08/09/2019, à 09:21

pingouinux

Re : [Résolu] recherche dans fichier

@kamaris #8 :
Après avoir testé tes commandes, il me semble que la première doive être :

mapfile -t fichiers < <(grep -rlZ 'texte1' "$rep_rech" | xargs -0 grep -l 'texte2')

Ça ne marche pas si le nom d'un fichier contient le caractère '\n'.

Hors ligne

#10 Le 08/09/2019, à 11:13

kamaris

Re : [Résolu] recherche dans fichier

Ah non, il me semble plutôt que c'est le contraire :

$ rep_rech='td'
$ ls "$rep_rech"
'f'$'\n'
$ cat "$rep_rech/f"$'\n'
texte1
texte2
$ 
$ mapfile -td '' fichiers < <(grep -rlZ 'texte1' "$rep_rech" | xargs -0 grep -lZ 'texte2')
$ grep -nHE 'texte1|texte2' "${fichiers[@]}"
td/f
:1:texte1
td/f
:2:texte2
$ 
$ unset fichiers
$ mapfile -t fichiers < <(grep -rlZ 'texte1' "$rep_rech" | xargs -0 grep -l 'texte2')
$ grep -nHE 'texte1|texte2' "${fichiers[@]}"
grep: td/f: Aucun fichier ou dossier de ce type
grep: : Aucun fichier ou dossier de ce type

Le saut de ligne peut être déplacé ou multiplié dans le nom de fichier avec le même résultat, à ceci près que le tableau « fichiers » contiendra alors plusieurs entrées : autant qu'il y a de chaines de caractères séparées par des sauts de lignes dans le nom du fichier.

Hors ligne

#11 Le 08/09/2019, à 11:41

pingouinux

Re : [Résolu] recherche dans fichier

@kamaris :
Je me suis mal exprimé en #9 : la commande que j'indique ne fonctionne pas non plus si le nom d'un fichier contient le caractère '\n'.

Nos mapfile semblent différents, le mien n'accepte pas l'option -d.

$ lsb_release -ds
Ubuntu 16.04.6 LTS
$ type mapfile
mapfile is a shell builtin
$ help mapfile
mapfile: mapfile [-n count] [-O origin] [-s count] [-t] [-u fd] [-C callback] [-c quantum] [array]
    Read lines from the standard input into an indexed array variable.
    
    Read lines from the standard input into the indexed array variable ARRAY, or
    from file descriptor FD if the -u option is supplied.  The variable MAPFILE
    is the default ARRAY.
    
    Options:
      -n count	Copy at most COUNT lines.  If COUNT is 0, all lines are copied.
      -O origin	Begin assigning to ARRAY at index ORIGIN.  The default index is 0.
      -s count 	Discard the first COUNT lines read.
      -t		Remove a trailing newline from each line read.
      -u fd		Read lines from file descriptor FD instead of the standard input.
      -C callback	Evaluate CALLBACK each time QUANTUM lines are read.
      -c quantum	Specify the number of lines read between each call to CALLBACK.
.............................................................................

Hors ligne

#12 Le 08/09/2019, à 13:02

kamaris

Re : [Résolu] recherche dans fichier

Ah ok, ça doit être une question de version de bash :

$ bash --version
GNU bash, version 5.0.9(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2019 Free Software Foundation, Inc.
Licence GPLv3+ : GNU GPL version 3 ou ultérieure <http://gnu.org/licenses/gpl.html>

Ceci est un logiciel libre ; vous être libre de le modifier et de le redistribuer.
AUCUNE GARANTIE n'est fournie, dans les limites permises par la loi.
$ 
$ help mapfile
mapfile: mapfile [-d délim] [-n nombre] [-O origine] [-s nombre] [-t] [-u fd] [-C callback] [-c quantum] [tableau]
    Lit des lignes depuis l'entrée standard vers une variable tableau indexé.
    
    Lit des lignes depuis l'entrée standard vers la variable tableau indexé TABLEAU ou
    depuis le descripteur de fichier FD si l'option « -u » est utilisée. La variable
    MAPFILE est le TABLEAU par défaut.
    
    Options :
      -d delim	Utilise DELIM pour terminer les lignes au lieu du saut de ligne
      -n nombre	Copie au maximum NOMBRE lignes.  Si NOMBRE est 0, toutes les lignes sont copiées.
      -O origine	Commence l'affectation au TABLEAU à l'indice ORIGINE.  L'indice par défaut est 0.
      -s nombre	Saute les NOMBRE premières lignes lues.
      -t	Retire les retours à la ligne de chaque ligne lue.
      -u fd	Lit les lignes depuis le descripteur de fichier FD au lieu de l'entrée standard.
      -C callback	Évalue CALLBACK à chaque fois que QUANTUM lignes sont lues.
      -c quantum	Indique le nombre de lignes lues entre chaque appel au CALLBACK.
    
    Arguments :
      TABLEAU	Nom de la variable tableau à utiliser pour les données.
    
    Si l'option « -C » est fournie sans option « -c », le quantum par défaut est 5000.
    Lorsque CALLBACK est évalué, l'indice du prochain élément de tableau qui sera affecté
    lui est transmis comme argument additionnel.
    
    Si la commande « mapfile » n'est pas appelée avec une origine explicite, le tableau est
    vidé avant affectation.
    
    code de retour :
    Renvoie le code de succès à moins qu'une option non valable ne soit donnée ou que
    le TABLEAU soit en lecture seule ou ne soit pas un tableau indexé.
$ 

Sinon, le mapfile peut être remplacé par un read :

IFS=''; i=0; fichiers=()
while read -rd '' fichier; do
  fichiers[$i]="$fichier"
  ((i++))
done < <(grep -rlZ 'texte1' "$rep_rech" | xargs -0 grep -lZ 'texte2')
unset IFS

-------

EDIT : eh bien, j'ai galéré, mais j'ai fini par trouver des release notes pour bash : https://tiswww.case.edu/php/chet/bash/NEWS, dans lesquelles on trouve :

https://tiswww.case.edu/php/chet/bash/NEWS a écrit :

This is a terse description of the new features added to bash-4.4 since the release of bash-4.3.  As always, the manual page (doc/bash.1) is the place to look for complete descriptions.

1.  New Features in Bash
[…]
d.  The `mapfile' builtin now has a -d option to use an arbitrary character
    as the record delimiter, and a -t option  to strip the delimiter as
    supplied with -d.

Dernière modification par kamaris (Le 08/09/2019, à 13:32)

Hors ligne

#13 Le 08/09/2019, à 14:00

pingouinux

Re : [Résolu] recherche dans fichier

C'est bien ça

$ bash --version
GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu)

En remplaçant mapfile par ta séquence (en #12) avec read, j'obtiens aussi les bons résultats.

Hors ligne

#14 Le 09/09/2019, à 10:25

ar barzh paour

Re : [Résolu] recherche dans fichier

merci à tous pour vos réponses
je suis actuellement dans un lieu avec accès à internet très très difficile ...
@Watael post#6
texte1 et texte2 peuvent apparaître dans n'importe quelle ligne (avant après) , et peut-être pas dans la même ligne

je vais étudier toutes les réponses .... à plus

Dernière modification par ar barzh paour (Le 09/09/2019, à 10:26)


Ubuntu 18.04 (sept 2018) (était en essai depuis 12/2017)
Ubuntu 16.04 (07/2016) et diverses versions  Ubuntu 14.04 ,  Studio 14.04 LTS 64 bits , MATE 16.04
PC          : Intel(R) Pentium(R) CPU G4600 @ 3.60GHz  + 4GiB RAM DDR4-2400
Portable : Intel(R) Core(TM)2  Duo CPU     T5750  @ 2.00GHz 3Go de RAM DDR2 667 Mhz Ubuntu 18.04

Hors ligne

#15 Le 10/09/2019, à 09:24

ar barzh paour

Re : [Résolu] recherche dans fichier

j'ai pris au hasard texte1=carpe texte2=hrand
ces scripts fonctionnent bien et même si je m'aperçois qu'il n'y a pas que du texte dans les fichiers
merci à tous , il me reste à affiner ma recherche

@MicP poste #2

rep_rech="/media/m/l/
find "$rep_rech" -depth -type f -name "*" -exec awk "/carpe|hrand/ {print FILENAME \" => Ligne N°\" NR \" => \" $ $0}" "{}" \; 2>/dev/null

/media//ml/ba5xxx/95 => Ligne N°11155 => Q3WGD7ki6kTJZ+CYW45Gjq/vCp9XuxjhZIDq/wCZs7j90qt9WbcarpeG02VyKWTJE8LU+1Yv
/media/m/l/ba5xxx/95 => Ligne N°94163 => IOcxnf9gL8n/6DqNhrandTn9Tn//MQLzBp3aLK5ax34wABGMDROMfmHMEaOMtOKMEEWMQGyM

@jamesbad000 poste #5

grep -E -nr "carpe|hrand" "$rep_rech"

$ grep -E -nr "carpe|hrand" "$rep_rech"

/media/m/l/ba5xxx/95:11155:Q3WGD7ki6kTJZ+CYW45Gjq/vCp9XuxjhZIDq/wCZs7j90qt9WbcarpeG02VyKWTJE8LU+1Yv
/media/m/l/ba5xxx/95:94163:IOcxnf9gL8n/6DqNhrandTn9Tn//MQLzBp3aLK5ax34wABGMDROMfmHMEaOMtOKMEEWMQGyM
Fichier binaire /media/m/l/dbxxx/f.db correspondant


@pingouinux poste #7

find "$rep_rech" -type f -exec ./rech_evolution_script.py "carpe" "hran" {} \; 2>/dev/null
/media/m/l/ba5xxx/95
11155:Q3WGD7ki6kTJZ+CYW45Gjq/vCp9XuxjhZIDq/wCZs7j90qt9WbcarpeG02VyKWTJE8LU+1Yv
94163:IOcxnf9gL8n/6DqNhrandTn9Tn//MQLzBp3aLK5ax34wABGMDROMfmHMEaOMtOKMEEWMQGyM

@kamaris poste #8

ne me donne rien

IFS=''; i=0; fichiers=()
while read -rd '' fichier; do
  fichiers[$i]="$fichier"
  ((i++))
done < <(grep -rlZ 'carpe' "$rep_rech" | xargs -0 grep -lZ 'hrand')
unset IFS

@kamaris poste #10

mapfile -td '' fichiers < <(grep -rlZ 'carpe' "$rep_rech" | xargs -0 grep -lZ 'hrand')
grep -nHE 'carpe|hrand' "${fichiers[@]}"

/media/m/l/ba5xxx/95:11155:Q3WGD7ki6kTJZ+CYW45Gjq/vCp9XuxjhZIDq/wCZs7j90qt9WbcarpeG02VyKWTJE8LU+1Yv
/media/m/l/ba5xxx/95:94163:IOcxnf9gL8n/6DqNhrandTn9Tn//MQLzBp3aLK5ax34wABGMDROMfmHMEaOMtOKMEEWMQGyM

Dernière modification par ar barzh paour (Le 10/09/2019, à 09:30)


Ubuntu 18.04 (sept 2018) (était en essai depuis 12/2017)
Ubuntu 16.04 (07/2016) et diverses versions  Ubuntu 14.04 ,  Studio 14.04 LTS 64 bits , MATE 16.04
PC          : Intel(R) Pentium(R) CPU G4600 @ 3.60GHz  + 4GiB RAM DDR4-2400
Portable : Intel(R) Core(TM)2  Duo CPU     T5750  @ 2.00GHz 3Go de RAM DDR2 667 Mhz Ubuntu 18.04

Hors ligne

#16 Le 10/09/2019, à 11:06

kamaris

Re : [Résolu] recherche dans fichier

ar barzh paour a écrit :

@kamaris poste #8

ne me donne rien

IFS=''; i=0; fichiers=()
while read -rd '' fichier; do
  fichiers[$i]="$fichier"
  ((i++))
done < <(grep -rlZ 'carpe' "$rep_rech" | xargs -0 grep -lZ 'hrand')
unset IFS

@kamaris poste #10

mapfile -td '' fichiers < <(grep -rlZ 'carpe' "$rep_rech" | xargs -0 grep -lZ 'hrand')
grep -nHE 'carpe|hrand' "${fichiers[@]}"

/media/m/l/ba5xxx/95:11155:Q3WGD7ki6kTJZ+CYW45Gjq/vCp9XuxjhZIDq/wCZs7j90qt9WbcarpeG02VyKWTJE8LU+1Yv
/media/m/l/ba5xxx/95:94163:IOcxnf9gL8n/6DqNhrandTn9Tn//MQLzBp3aLK5ax34wABGMDROMfmHMEaOMtOKMEEWMQGyM

C'est normal que le premier code ne te renvoie rien : comme je le disais en #12, il remplace le mapfile (et seulement le mapfile), au cas où on aurait pas l'option -d, comme pingouinux.
Pour avoir le résultat voulu, il faut ensuite faire

grep -nHE 'carpe|hrand' "${fichiers[@]}"

Hors ligne