grep pour plusieurs strings dans les files, puis listz les files dans l'ordre de grandeur

Je suis dans un dossier avec beaucoup de file .txt , je voudrais find tous les files qui contiennent à la fois ssortingngA et ssortingngB (pas nécessairement sur la même ligne), puis listr ces files dans l'ordre de la taille (du plus petit au plus grand )

J'ai essayé le suivant, mais ça ne marche pas:

 ls -lS | for f in *; do grep -q ssortingngA $f && grep -l ssortingngB $f; done 

Quelqu'un at-il une bonne idée?

Vous pouvez utiliser GNU find :

 find . -maxdepth 1 -exec grep -q ssortingngA {} \; -exec grep -q ssortingngB {} \; \ -printf '%10s %p\n' | sort -n 

Utilisation de perl (portable et pas de problème avec l'espace dans les noms de files):

 perl -Mautodie -wle ' for (<"*.txt">) { open my $fh, "<", $_; my @list = <$fh>; close $fh; if (grep { /ssortingngA/ } @list and grep { /ssortingngB/ } @list) { $h->{$_}->{size} = (stat($_))[8]; } } END{ print join "\n", sort { $h->{$a}->{size} <=> $h->{$b}->{size} } keys %$h; } ' 

Avec les outils zsh et GNU:

 grep -lZ -- ssortingngA *.txt(oL) | xargs -r0 grep -l -- ssortingngB 

Méthode # 1

Vous pourriez utiliser la string suivante:

 $ grep -l ssortingngA * | tr '\n' '\0' | xargs -0 grep -l ssortingngB | xargs du | sort -nr 

Le tr convertit la sortie de grep sorte que si des noms de files incluent des espaces, ils seront protégés à l'avenir. Tout le rest est assez simple. L'utilisation de xargs pour exécuter la sortie d'une command précédente à travers la command suivante, est un model typique dans Unix.

Vous pouvez renoncer au bit tr et utiliser le commutateur -Z de grep .

 $ grep -lZ ssortingngA * | xargs -0 grep -l ssortingngB | xargs du | sort -nr 

Exemple

 $ grep -lZ ssortingngA * | xargs -0 grep -l ssortingngB | xargs du | sort -nr 9220 ssortingngA99ssortingngB.txt 8196 ssortingngA88ssortingngB.txt 7172 ssortingngA77ssortingngB.txt 6148 ssortingngA66ssortingngB.txt 5124 ssortingngA55ssortingngB.txt 4100 ssortingngA44ssortingngB.txt 3076 ssortingngA33ssortingngB.txt 2052 ssortingngA22ssortingngB.txt 1028 ssortingngA11ssortingngB.txt 4 ssortingngAspacessortingngB.txt 

Méthode # 2

Approche similaire sauf au lieu de l'utilisation de du | sort du | sort juste canaliser la sortie à ls -lS similaire à votre approche.

 $ grep -lZ ssortingngA * | xargs -0 grep -l ssortingngB | xargs ls -lS 

Exemple

 $ grep -lZ ssortingngA * | xargs -0 grep -l ssortingngB | xargs ls -lS -rw-rw-r-- 1 saml saml 9437200 Aug 6 15:15 ssortingngA99ssortingngB.txt -rw-rw-r-- 1 saml saml 8388624 Aug 6 15:15 ssortingngA88ssortingngB.txt -rw-rw-r-- 1 saml saml 7340048 Aug 6 15:15 ssortingngA77ssortingngB.txt -rw-rw-r-- 1 saml saml 6291472 Aug 6 15:15 ssortingngA66ssortingngB.txt -rw-rw-r-- 1 saml saml 5242896 Aug 6 15:15 ssortingngA55ssortingngB.txt -rw-rw-r-- 1 saml saml 4194320 Aug 6 15:15 ssortingngA44ssortingngB.txt -rw-rw-r-- 1 saml saml 3145744 Aug 6 15:15 ssortingngA33ssortingngB.txt -rw-rw-r-- 1 saml saml 2097168 Aug 6 15:15 ssortingngA22ssortingngB.txt -rw-rw-r-- 1 saml saml 1048592 Aug 6 15:15 ssortingngA11ssortingngB.txt -rw-rw-r-- 1 saml saml 32 Aug 6 15:35 ssortingngAspacessortingngB.txt 

Méthode # 3

Celui-ci utilise la capacité de grep à utiliser le moteur d'expression régulière de Perl (PCRE).

 $ grep -Pzol "(?s)ssortingngA.*ssortingngB" * | xargs ls -lS 

Cette méthode est un peu plus lente car le file est en cours de conversion de sorte que la fin des lignes se termine par des caractères NULL ( \0 ) au lieu de newlines ( \n ).

  • -P active perl-regexp pour grep (une extension puissante des extensions régulières)
  • -z supprime la nouvelle ligne en fin de ligne, en la remplaçant par le caractère nul. C'est-à-dire que grep sait où se trouve la fin de la ligne, mais voit l'input comme une grande ligne.
  • -o imprimer uniquement correspondant. Parce que nous utilisons -z , le file entier est comme une seule grande ligne, donc s'il y a une correspondance, le file entier sera imprimé; De cette façon, il ne fera pas cela.

En regexp:

  • (?s) activer PCRE_DOTALL, ce qui signifie que . trouve un caractère ou une nouvelle ligne

Les references

  • Regex (grep) pour la search multiligne nécessaire [duplicate]
  egrep -l '(ssortingngA|ssortingngB)' * | xargs ls -1S 

egrep autorise les expressions régulières, de sorte que le file ci-dessus search chaineA OU stringB dans tous les files, l'option -l indique à egrep de ne produire que les files correspondants (et de supprimer la sortie des lignes correspondantes). La passer à xargs ls -1S transmettra tous les files correspondants à ls -1S . -1 indique à ls d'énumérer un file par ligne et -S indique à ls de sortinger par taille de file plutôt que par nom.

EDIT Oups c'est un OU (mauvaise lecture de la question).

Dans ce cas, une adaptation de la solution de sputnick pour utiliser deux greps

 grep -l ssortingngA * | xargs grep -l ssortingngB | xargs -ls -1S 

(au less contourner du et sort il y a un process de less 🙂