grep для нескольких строк в файлах, и затем перечисляют файлы в порядке размера

Для окраски вывода от ls используйте псевдоним ls='ls --color=always'. Можно включить это с

alias ls='ls --color=always'

Что касается наличия Вашего текущего каталога в Вашей подсказке:

PROMPT='%~'

Чтобы добавить состояние мерзавца к Вам подсказка, смотрите на это.

4
06.08.2013, 21:36
5 ответов

Можно использовать GNU find:

find . -maxdepth 1 -exec grep -q stringA {} \; -exec grep -q stringB {} \; \
        -printf '%10s %p\n' | 
    sort -n
5
27.01.2020, 20:47
  • 1
    printf аргумент к find не POSIX, но это - хорошее решение. –  jordanm 06.08.2013, 21:42

Используя (портативный и без проблем с пространством в именах файлов):

perl -Mautodie -wle '
    for (<"*.txt">) {
        open my $fh, "<", $_;
        my @list = <$fh>;
        close $fh;
        if (grep { /stringA/ } @list and grep { /stringB/ } @list) {
            $h->{$_}->{size} = (stat($_))[8];
        }
    }
    END{
        print join "\n", sort { $h->{$a}->{size} <=> $h->{$b}->{size} } keys %$h;
    }
'
2
27.01.2020, 20:47
  • 1
    Портативный хорошо, но загрузка всего файла в массив и затем использование grep в булевом контексте (дважды) довольно неэффективно. –  jordanm 07.08.2013, 07:22

С zsh и инструменты GNU:

grep -lZ -- stringA *.txt(oL) | xargs -r0 grep -l -- stringB
2
27.01.2020, 20:47

Метод № 1

Вы могли использовать следующую цепочку:

$ grep -l stringA * | tr '\n' '\0' | xargs -0 grep -l stringB | xargs du | sort -nr

tr преобразовывает вывод grep так, чтобы, если какие-либо имена файлов включают пробелы, они были защищены, продвинувшись. Все остальное довольно просто. Использование xargs для выполнения вывода от предыдущей команды до следующей команды, типичный шаблон в Unix.

Можно предшествовать tr бит и использует grep -Z переключатель.

$ grep -lZ stringA * | xargs -0 grep -l stringB | xargs du | sort -nr

Пример

$ grep -lZ stringA * | xargs -0 grep -l stringB | xargs du | sort -nr
9220    stringA99stringB.txt
8196    stringA88stringB.txt
7172    stringA77stringB.txt
6148    stringA66stringB.txt
5124    stringA55stringB.txt
4100    stringA44stringB.txt
3076    stringA33stringB.txt
2052    stringA22stringB.txt
1028    stringA11stringB.txt
4   stringAspacestringB.txt

Метод № 2

Аналогичный подход кроме вместо использования du | sort просто передайте вывод по каналу к ls -lS подобный Вашему подходу.

$ grep -lZ stringA * | xargs -0 grep -l stringB | xargs ls -lS

Пример

$ grep -lZ stringA * | xargs -0 grep -l stringB | xargs ls -lS
-rw-rw-r-- 1 saml saml 9437200 Aug  6 15:15 stringA99stringB.txt
-rw-rw-r-- 1 saml saml 8388624 Aug  6 15:15 stringA88stringB.txt
-rw-rw-r-- 1 saml saml 7340048 Aug  6 15:15 stringA77stringB.txt
-rw-rw-r-- 1 saml saml 6291472 Aug  6 15:15 stringA66stringB.txt
-rw-rw-r-- 1 saml saml 5242896 Aug  6 15:15 stringA55stringB.txt
-rw-rw-r-- 1 saml saml 4194320 Aug  6 15:15 stringA44stringB.txt
-rw-rw-r-- 1 saml saml 3145744 Aug  6 15:15 stringA33stringB.txt
-rw-rw-r-- 1 saml saml 2097168 Aug  6 15:15 stringA22stringB.txt
-rw-rw-r-- 1 saml saml 1048592 Aug  6 15:15 stringA11stringB.txt
-rw-rw-r-- 1 saml saml      32 Aug  6 15:35 stringAspacestringB.txt

Метод № 3

Этот использует grepспособность использовать механизм регулярного выражения Perl (PCRE).

$ grep -Pzol "(?s)stringA.*stringB" * | xargs ls -lS

Этот метод немного медленнее, потому что файл преобразовывается так, чтобы это был конец строк, завершаются с нулевыми символами (\0) вместо новых строк (\n).

  • -P активируйте perl-regexp для grep (мощное расширение регулярных расширений)
  • -z подавите новую строку в конце строки, заменив им нулевой символ. Таким образом, grep знает, где конец строки, но рассматривает вход как одну большую строку.
  • -o распечатайте только соответствие. Поскольку мы используем -z, целый файл похож на единственную большую строку, поэтому если бы существует соответствие, весь файл был бы распечатан; этим путем это не сделает этого.

В regexp:

  • (?s) активируйте PCRE_DOTALL, что означает это . находит любую символьную или новую строку

Ссылки

2
27.01.2020, 20:47
 egrep -l '(stringA|stringB)' * | xargs ls -1S

egrep допускает регулярные выражения, таким образом, вышеупомянутое будет искать stringA ИЛИ stringB во всех файлах, -l опция говорит egrep просто производить подобранные файлы (и подавите вывод согласующих отрезков длинной линии). Передача по каналу его к xargs ls -1S передаст все соответствия файлов ls -1S. -1 говорит ls перечислять один файл на строку и -S говорит ls виду размером файла, а не по имени.

ОТРЕДАКТИРУЙТЕ ООП, это ИЛИ (неправильно читавшее вопроса).

В этом случае адаптация решения sputnick использовать две власти

grep -l stringA * | xargs grep -l stringB | xargs -ls -1S

(по крайней мере, двигающийся du и sort существует тот меньше процесса :)

0
27.01.2020, 20:47
  • 1
    Это неправильно двумя способами: 1) OP просят обе строки на каждом файле; 2) команда перестала работать на именах файлов, содержащих –  enzotib 06.08.2013, 21:48
  • 2
    OP пробелов, который спрашивают a И, не a ИЛИ –  Gilles Quenot 06.08.2013, 21:48

Теги

Похожие вопросы