Comment utiliser awk pour la recherche de plusieurs fichiers dans deux répertoires, imprimer des enregistrements uniquement à partir de fichiers avec la chaîne correspondante dans le deuxième répertoire

Refaire une question précédente pour qu’elle soit plus claire. J’essaie de rechercher des fichiers dans deux répertoires et d’imprimer les chaînes de caractères correspondantes (+ ligne immédiatement après) dans un nouveau fichier du deuxième répertoire uniquement si elles correspondent à un enregistrement du premier répertoire. J’ai trouvé des exemples similaires mais rien de pareil. Je ne sais pas comment utiliser awk pour plusieurs fichiers de différents répertoires et je me suis torturé en essayant de le comprendre.

Répertoire 1, 28 000 fichiers, formaté à savoir. :

>ABC KLSDFIOUWERMSDFLKSJDFKLSJDSFKGHGJSNDKMVMFHKSDJFS >GHI OOILKJSDFKJSDFLMOPIWERIOUEWIRWIOEHKJTSDGHLKSJDHGUIYIUSDVNSDG 

Répertoire 2, 15 fichiers, formaté viz. :

 >ABC 12341234123412341234123412341234123412341234123412341234123412341234 >DEF 12341234123412341234123412341234 >GHI 12341234123412341234123412341234123412341234123412341234123412341234123412341234 

Sortie désirée:

 >ABC 12341234123412341234123412341234123412341234123412341234123412341234 >GHI 12341234123412341234123412341234123412341234123412341234123412341234123412341234 

Les répertoires 1 et 2 se trouvent dans mon répertoire personnel: (./Test1 & ./Test2)

Si quelqu’un pouvait conseiller à la commande de spécifier les différents répertoires, je vous serais très reconnaissant! Actuellement, lorsque j’inclus le chemin du fichier (par exemple, /Test1/*.fa), j’obtiens l’erreur suivante:

 awk: can't open file /Test1/*.fa 

Vous voudrez quelque chose comme ça (non testé):

 awk ' FNR==1 { dirname = FILENAME sub("/.*","",dirname) if (NR==1) { dirname1 = dirname } } dirname == dirname1 { if (FNR % 2) { key = $0 } else { map[key] = $0 } next } (FNR % 2) && ($0 in map) && !seen[$0,map[$0]]++ { print $0 ORS map[$0] } ' Test1/* Test2/* 

Étant donné que vous obtenez le message d’erreur /usr/bin/awk: Argument list too long ce qui signifie que vous avez dépassé la longueur maximale d’argument pour une commande et que 28 000 fichiers se trouvent dans le répertoire Test1, essayez ceci:

 find Test1 -type f -exec cat {} \; | awk ' NR == FNR { if (FNR % 2) { key = $0 } else { map[key] = $0 } next } (FNR % 2) && ($0 in map) && !seen[$0,map[$0]]++ { print $0 ORS map[$0] } ' - Test2/* 

Solution en TXR :

Les données:

 $ ls dir *
 dir1:
 fichier1 fichier2

 dir2:
 fichier1 fichier2

 $ cat dir1 / fichier1
 > ABC
 KLSDFIOUWERMSDFLKSJDFKLSJDSFKGHGJSNDKMVMFHKSDJFS
 > GHI
 OOILKJSDFKJSDFLMOPIWERIOUEWIRWIOEHKJTSDGHLKSJDHGUIYIUSDVNSDG

 $ cat dir1 / fichier2
 > XYZ
 SDOIWEUROIUOIWUEROIWUEROIWUEROIWUEROUIEIDIDIIDFIFI
 > MNO
 OOIWEPOIUWERHJSDHSDFJSHDF

 $ cat dir2 / fichier1
 > ABC
 12341234123412341234123412341234123412341234123412341234123412341234
 > DEF
 12341234123412341234123412341234
 > GHI
 12341234123412341234123412341234123412341234123412341234123412341234123412341234

 $ cat dir2 / fichier2
 > STP
 12341234123412341234123412341234123412341234123412341234123412341234123412341234
 > MNO
 123412341234123412341234123412341234123412341234123412341234123412341234
 $

Courir:

 $ txr filter.txr dir1 / * dir2 / *
 > ABC
 12341234123412341234123412341234123412341234123412341234123412341234
 > GHI
 12341234123412341234123412341234123412341234123412341234123412341234123412341234
 > MNO
 123412341234123412341234123412341234123412341234123412341234123412341234

Code dans filter.txr :

 @(bind want @(hash :equal-based)) @(next :args) @(all) @dir/@(skip) @(and) @ (repeat :gap 0) @dir/@file @ (next `@dir/@file`) @ (repeat) >@key @ (do (set [want key] t)) @ (end) @ (end) @(end) @(repeat) @path @ (next path) @ (repeat) >@key @datum @ (require [want key]) @ (output) >@key @datum @ (end) @ (end) @(end) 

Pour séparer les chemins dir1 du rest, nous utilisons une correspondance @(all) (essayez plusieurs twigs de modèle, qui doivent toutes correspondre) avec deux twigs. La première twig correspond à un @dir/@(skip) , liant la variable dir au texte précédé d’une barre oblique et ignorant le rest. La deuxième twig correspond à une séquence entière consécutive de motifs de @dir/@file via @(repeat :gap 0) . Comme la même variable dir apparaît déjà avec une liaison de la première twig du all , cela contraint les correspondances au même nom de répertoire. A l’intérieur de cette repeat nous rentrons dans chaque fichier via next et rassemblons les clés délimitées par une valeur > dans le hash keep . Après cela, nous traitons les arguments restants en tant que noms de chemin d’access des fichiers à traiter; ils ne doivent pas tous être dans le même répertoire. Nous parcourons chacun d’eux pour le motif >@key suivi d’une ligne de @datum . La directive @(require ...) échouera si la key n’est pas dans le hachage wanted , sinon nous tomberons sur la @(output) .