У меня есть десятки папок, которые содержат как простые текстовые файлы журнала, так и сжатые старые журналы. Моя цель - запустить только один вкладыш (по одной папке за раз), чтобы получить все результаты grep в соответствии с порядком отметок времени, независимо от того, является ли файл журнала, содержащий совпадение, txt или gz, и, если возможно, оптимизировать производительность.
Это прекрасно работает для простых файлов:
ls -rt log.*.txt | xargs grep <treasure> -
Я использую это, а не просто grep, поэтому результаты сортируются в хронологическом порядке создания файла, возможно, в течение нескольких дней, а не сортируются по имени файла. Имена файлов (log. #. 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 или чего-то еще полностью.
man zgrep
: "В противном случае данные файлы при необходимости распаковываются и передаются в grep." (выделено мое)Ответы:
Вот несколько вещей не так:
Старайтесь не перебирать или передавать результаты, полученные
ls
в другом инструменте. Он сломается, если файлы содержат пробелы или символы новой строки, в зависимости от того, как составлена команда. В вашем случае, однако, нет простого способа выполнить то, что вы хотите, кроме как использоватьls
. Так что, если вы знаете, что имена ваших файлов не будут содержать символ новой строки, тогда вы в порядке.<treasure> -
будет интерпретироваться оболочкой как перенаправление. Первая скобка<
будет читаться оболочкой, что означает «читать STDIN из файла с именемtreasure
». Второе значение в скобках читается как> -
«запись STDOUT в файл с именем-
». Таким образом, вы должны правильно цитировать шаблон , который вы пытаетесь прочитать:grep "<treasure>"
.-0
Опцияxargs
считывает входные данные как ASCII , NUL-разделители строк, которыеls
не будут производить. Это полезно только в сочетании с инструментами, которые могут создавать выходные данные, разделенные NUL, например,find
с помощью-print0
опции.Я не понимаю цели
-
ваших команд.Итак, попробуйте что-то вроде этого:
или же:
Объяснение:
extglob
позволяет сопоставить оба расширения файла-1
делаетls
один файл в каждой строке+(…|…)
означает «один или несколько» шаблона-L1
,xargs
будет передавать только один файл заzgrep
один раз. Это может быть не то, что вы хотите, хотя.источник
Что о:
источник