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

Это прекрасно работает для простых файлов:

ls -rt log.*.txt | xargs grep <treasure> -

Я использую это, а не просто grep, поэтому результаты сортируются в хронологическом порядке создания файла, возможно, в течение нескольких дней, а не сортируются по имени файла. Имена файлов (лог.# .txt) увеличиваться до определенного целочисленного предела, затем переходить к log.0.txt, но это может пересечь 24-часовую отметку или нет.

После переноса txt-файлов старые файлы распаковываются: log.# .Archive.gz. Сохраняются только файлы gz с целочисленным ограничением.

Я думал использовать оператор if/fi для grep или zgrep в зависимости от расширения текущего файла. Однако, мой первый шаг, чтобы попробовать это только на файлах gz, не работал:

ls -rt log.*.gz | xargs zgrep <treasure> -

Я получаю кучу ошибок "файл 'сокровище' не найден" (по одной на каждый файл .gz)

Я также пытался

ls -rt "log.*.gz" | xargs -0 zgrep <treasure> -

к тому же результату. Я знал, что это должно быть из-за моего элементарного понимания команды xargs. Может быть, я даже смогу сделать это с помощью соответствующих опций grep/zgrep, find или чего-то еще.

2 ответа2

0

Вот несколько вещей не так:

  • Старайтесь не перебирать или выводить вывод ls в другой инструмент. Он сломается, если файлы содержат пробелы или символы новой строки, в зависимости от того, как составлена команда. В вашем случае, однако, нет простого способа выполнить то, что вы хотите, кроме использования ls . Так что, если вы знаете, что имена ваших файлов не будут содержать символ новой строки, тогда вы в порядке.

  • <treasure> - будет интерпретироваться оболочкой как перенаправление. Первая скобка < будет читаться оболочкой, что означает «читать STDIN из файла с именем treasure ». Второе значение в скобках будет читаться как > - , то есть «записать STDOUT в файл с именем - ». Итак, вы должны правильно процитировать шаблон, который вы пытаетесь прочитать: grep "<treasure>" .

  • Параметр -0 для xargs читает ввод как строки, разделенные NUL ASCII, которые ls не будет производить. Он полезен только в сочетании с инструментами, которые могут создавать выходные данные с разделением NUL, например find с параметром -print0 .

  • Я не понимаю цели - в ваших командах.

Итак, попробуйте что-то вроде этого:

shopt -s extglob
ls -rt1 +(log.*.txt|log.*.gz) | xargs zgrep "<treasure>"

или же:

ls -rt1 +(log.*.txt|log.*.gz) | xargs -L1 zgrep "<treasure>"

Объяснение:

  • extglob позволяет сопоставить оба расширения файла
  • -1 заставляет ls выводить по одному файлу на строку
  • +(…|…) Означает "один или несколько" шаблона
  • Если вы используете -L1 xargs будет проходить только один файл zgrep в то время. Это может быть не то, что вы хотите, хотя.
-1

Как насчет:

for each in `ls -rt log.*.gz`; do zgrep "<TREASURE>" $each; done

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .