Поиск файлов с совпадающими целыми строками из файла

Веб-браузером по умолчанию в среде Debian KDE является Konqueror. Убедитесь, что установлен веб-браузер по умолчанию.

$ xdg-settings get default-web-browser

Из вики debian для KDE :В разделе «Системные настройки» -> «Приложения по умолчанию» -> «Веб-браузер» измените URL-адреса «Открыть http» и «https» на «в следующем браузере :» и введите путь к исполняемый файл браузера (, например, /usr/bin/iceweasel ).

Если вам нужно настроить браузер по умолчанию для системы, используйте:

# update-alternatives --config x-www-browser

Вам будет предложено установить параметры. Выберите тот, который вы хотите использовать. Если это все еще не работает, запустите команду еще раз и попробуйте другой вариант (, если есть другой доступный ).

Если другого варианта для выбора нет. Попробуйте установить другой веб-браузер, например Chrome, и установите его по умолчанию.

4
07.04.2021, 03:12
7 ответов

Использование awk, который поддерживаетnextfile:

NR == FNR {
  a[++n]=$0; next
}
$0 != a[c+1] && (--c || $0!=a[c+1]) {
  c=0; next
}
++c >= n {
  print FILENAME; c=0; nextfile
}

с findдля рекурсии:

find dir -type f -exec gawk -f above.awk compromised_header.txt {} +

Или это может сработать:

pcregrep -rxlM "$( perl -lpe '$_=quotemeta' compromised_header.txt )" dir

Использование perl для экранирования метасимволов, потому что pcregrep не сочетает --fixed-stringsс --multiline.

Perl в режиме slurp (не будет работать с файлами, которые слишком велики для хранения в памяти):

find dir -type f -exec perl -n0777E 'BEGIN {$f=<>} say $ARGV if /^\Q$f/m
' compromised_header.txt {} +
8
28.04.2021, 22:54

Если у вас есть GNU grep с режимом PCRE -P, вы работаете в режиме slurp -z и рекурсивно -r выводит список -l файлов, соответствующих регулярному выражению $re. Регулярное выражение строится из ссылочного заголовочного файла и экранирует все специальные символы в контексте регулярных выражений для Perl.

re=$(< compromised_header.txt perl -lpe '$_=quotemeta')
re=${re//[${IFS#??}]/\\n}
grep -lrzP "(?m)^$re".
4
28.04.2021, 22:54

Предполагая, что ваша строка поиска не имеет нескольких завершающих символов новой строки или символов ASCII NUL (см. подводные камни чтения файла в переменную оболочки для подробностей )и вы согласны с использованием ripgrep:

rg -lUF "$(< compromised_header.txt)" dir/

-Fопция используется для того, чтобы содержимое файла искалось буквально, а не рассматривалось как регулярное выражение

-Uопция включает многострочный поиск

rgбудет выполнять рекурсивный поиск по умолчанию, однако он также выполняет интеллектуальную фильтрацию по умолчанию (соблюдает правила .gitignore,игнорирует скрытые файлы/папки, игнорирует двоичные файлы и т. д. ). Используйте -uuu, чтобы заставить его вести себя как grep -r.


См. мой пост в блоге Многострочный поиск фиксированной строки и замена с помощью инструментов cli для большего количества таких многострочных операций.

4
28.04.2021, 22:54
GNU grep :
grep -lzFf compromised_header.txt -r dir/
  • -z => "строки" заканчиваются нулевым байтом вместо новой строки
  • -Шаблон F => — фиксированная строка, а не регулярное выражение
  • -f файл => образцы считываются из файла

Критика в комментариях вполне -обоснована :Я недостаточно тщательно проверял.

Другая попытка более сложная :она заменяет новые строки в файле шаблона и поисковых файлах необычным символом ASCII:

find. -type f -print0 \
| xargs -0 bash -c '
    pattern=$(tr "\n" "\x1e" <./compromised_header.txt)
    for file; do 
        tr "\n" "\x1e" < "$file" | grep -qF "$pattern" && echo "$file"
    done
' bash
2
28.04.2021, 22:54
$ cat tst.awk
NR==FNR {
    lines[++numLines] = $0
    next
}
FNR == 1 {
    expected = lines[++lineNr]
}
$0 == expected {
    if ( lineNr == numLines ) {
        print FILENAME
        found = 1
        exit
    }
    expected = lines[++lineNr]
}
END {
    exit !found
}

$ awk -f tst.awk compromised_header.txt 'a-compromised-file.txt'
a-compromised-file.txt

$ echo $?
0

Поместите приведенное выше в find, чтобы запустить его в подкаталогах:

find dir -type f -exec awk -f tst.awk compromised_header.txt {} \;

Обратите внимание, что вам нужно использовать \;, а не +в конце команды find, чтобы )она работала с каждой версией findи каждой версией awk., а b)awkвызывается по одному файлу за раз, так как это необходимо для установки переменных и выхода с правильным статусом.

4
28.04.2021, 22:54

Учитывая ввод:

$ head -n -0 ?-compromised-file.txt
==> a-compromised-file.txt <==
this content is in a-compromised-file.txt
some unique string 1
some other unique string 2
another unique string 3
unrelated line x
unrelated line y
unrelated line z

==> b-compromised-file.txt <==
this content is in b-compromised-file.txt
some unique string 1
another unique string 3
some other unique string 2
unrelated line x
unrelated line y
unrelated line z

==> c-compromised-file.txt <==
this content is in c-compromised-file.txt
some unique string 1
some unique string 1
some other unique string 2
another unique string 3
unrelated line x
unrelated line y
unrelated line z

... этот Perl-скрипт:

while (<>) {
    # Read the pattern from the first file.
    $pattern.= $_;
    last if eof;
}
# Search remaining files for the pattern.
while (<>) {
    # If existing buffer continues matching pattern, or if
    # the current line matches the beginning of pattern...
    if (($buf.= $_) eq substr($pattern,0,length($buf))
        or (($buf = $_) eq substr($pattern,0,length($buf)))
    ) { 
        # If we successfully match the whole pattern, move along.
        if ($pattern eq $buf) {
            print $ARGV, "\n";
            $buf = q{};
            do {$_ = <>} until eof; # skip to end of current file
        }
    }
    else { $buf = q{}; }
}

... дает следующие результаты:

$ find. -name '*-compromised-file.txt' | xargs perl above.pl compromised_header.txt
./a-compromised-file.txt
./c-compromised-file.txt

Он не потребляет памяти, не подвергается интерполяции регулярных выражений и прекращает поиск дополнительных совпадений в файле, если они уже найдены. Я надеюсь, что это прокомментировано достаточно хорошо, чтобы следовать.

Что касается некоторых других ответов/комментариев, будьте осторожны с режимом slurp, если у вас большие файлы, так как вы можете столкнуться с ограничениями памяти.

Обратите внимание, что c -скомпрометированный -файл.txt, показанный выше, не соответствует по крайней мере одному из других ответов. (У меня пока недостаточно репутации, чтобы комментировать там.)

2
28.04.2021, 22:54

Мы можем выполнить обнаружение заголовка, используя GNU sed и предоставив несколько файлов, но используя опцию -s, чтобы разделить потоки.

ref=$(< compromised_header.txt sed -e 's:[\&/]:\\&:g;$!s:$:\\:')
find dir -type f -exec \
sed -sEn "
  1{x;/^\$/s/.*/$ref/;x;}"'
  /\n/!G
  /^([^\n]*)\n\1(\n|$)/!{
    G;/^[^\n]*\n(.*)\n\1$/d
    s/\n.*//;s/^/\n/;D
  }
  s///;/^$/{F;:n;n;$!bn;}
  $d;N
  s/(.*)((\n).*)/\2\3\1/;D
' {} +

Сохраните скомпрометированный заголовок после того, как должным образом сделаете его подключаемым в RHS sed. Затем мы сравниваем его с поступающими данными. Для совпадения мы обрезаем верхний элемент удержания и читаем следующую строку. Это останавливается, когда трюм опустошается и печатается имя файла. И если есть несоответствие, мы восстанавливаем удержанную часть в пространстве шаблонов, которая могла быть использована до этого момента, и повторяем действия с этого момента.

#==============================

Ниже приведен еще один метод, в котором используются различные утилиты Linux. Общая идея заключается в том, что номер первой строки заголовка в файле определяется с помощью grep. Далее, начиная с этого, через редактор ed извлекается кусок, равный по размеру заголовочному файлу, и сравнивается с заголовком. Печатать имя файла при совпадении. Зацикливание выполняется через find.

find. -type f -exec sh -c '
  tick='\\\''
  ref=$1;shift
  L1=$(< "$ref" head -n1)
  len=$(dc -e "$(< "$ref" wc -l) 1-f")
  for f do
  set -- $(grep -nxFe "$L1" < "$f" | cut -d: -f1)
  for lnum do
    ed -s "$f" <<eof |\
    cmp -s - "$ref" && {\
    printf "%s\\n" "$f";break;}
${lnum}kx
${tick}x,${tick}x+${len}p
Q
eof
  done;done
' find-sh compromised_header.txt {} +
1
28.04.2021, 22:54

Теги

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