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
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
$ 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
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
$ 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
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 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 🙂