Как найти журналы, которые содержат определенную строку в большом количестве gz/regular файлов и сохраняют ее как один/больше txt файлы?

Новый вопрос 22.09.2016, вниз ниже!

Мой путь похож на это:

~/Desktop/logs
├── first_folder
|   ├── 11.11 (folder)
│   |   ├── access_log
│   |   ├── access_log.1.gz
│   |   :
│   |   └── access_log.40.gz
|   └── 11.12 (folder)
│       ├── access_log
│       ├── access_log.1.gz
│       :
│       └── access_log.16.gz
├── second_folder (folder)
|   ├── 31.11 (folder)
│   |   ├── access_log
│   |   ├── access_log.1.gz
│   |   :
│   |   └── access_log.20.gz
|   └── 31.15 (folder)
│       ├── access_log
│       ├── access_log.1.gz
│       :
:       └── access_log.38.gz
└── last_folder
    ├── 91.11 (folder)
    |   ├── access_log
    |   ├── access_log.1.gz
    |   :
    |   └── access_log.25.gz
    └── 91.15 (folder)
        ├── access_log
        ├── access_log.1.gz
        :
        └── access_log.30.gz

От всех журналов я должен извлечь данные, которые содержат строку: /Jan/2016

Вопрос № 1

Как я могу получить все записи из всех файлов во всех папках и сохранить его как single_file.txt

Редактирование № 1

Возможный ответ:

$ find . -name \*.* | xargs -0 zgrep -E '/Jan/2016' > single_file.txt

Файл действительно действительно огромен, много ГБ.

Вывод:

single_file.txt
./first_folder/11.11/access_log.9.gz: ... text ...
./first_folder/11.12/access_log.9.gz: ... text ...
./second_folder/31.11/access_log.9.gz: ... text ...
./second_folder/31.11/access_log.9.gz: ... text ...
:

Вопрос № 2

Как я могу получить все записи из всех файлов во всех папках и сохранить их индивидуально в зависимости от записей, как которые я захватываю от first_folder, second_folder и т.д. first.txt, second.txt.

Вывод посмотрел бы что-то как:

first.txt
./first_folder/11.11/access_log.9.gz: ... text ...
./first_folder/11.12/access_log.9.gz: ... text ...
:
second.txt
./second_folder/31.11/access_log.9.gz: ... text ...
./second_folder/31.15/access_log.9.gz: ... text ...
:

Вопрос № 3

Как я могу получить список всех файлов, которые содержат строку /Jan/2016?

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

$ find ~/Desktop/logs/ -type f | xargs zgrep -l "/Jan/2016"  

Вывод:

Terminal
/home/name/Desktop/logs/first_folder/11.11/access_log.9.gz
/home/name/Desktop/logs/first_folder/11.12/access_log.8.gz
/home/name/Desktop/logs/second_folder/31.11/access_log.6.gz
:

Редактирование № 2

@waltinator-s код и @Zanna-s исправление:

pushd ~/Desktop/logs
for dir in * ; do
    if [[ -d "$dir" ]] ; then
        outname="$dir.txt"
        find "$dir" -type f -print0 | xargs -0 zgrep -l '/Jan/2016' >"$outname"
    fi
done
popd

даст мне структуру:

~/Desktop/logs
├── first_folder
|   └── first.txt
├── second_folder
|   └── second.txt
:
└── last_folder
    └── last.txt

где first.txt-last.txt будет содержать пути к определенным файлам, которые содержат строку/Jan/2016.

first.txt
first_folder/11.11/access_log.9.gz
first_folder/11.11/access_log.8.gz
first_folder/11.12/access_log.9.gz
first_folder/11.12/access_log.8.gz

Вопрос № 4 (22.9.2016)

Я должен был изменить /Jan/2016 к определенному промежутку времени..., например, 1/Nov/2014-31/Apr/2015 таким образом в коде, что @Zana, обеспеченный вместо /Jan/2016 Я использовал /(Nov|Dec)/2014|/(Jan|Feb|Mar|Apr)/2015. Предупреждение брошено:

xargs: Warning: a NUL character occurred in the input.  It cannot be passed through in the argument list.  Did you mean to use the --null option?

Все результаты не возвращаются в созданных файлах, хотя все файлы создаются.

3
задан 23 September 2016 в 00:16

2 ответа

  1. Имейте данные, которые содержат строку в отдельные текстовые файлы в зависимости от папки (пример: первая папка - first.txt и т.д.)

Вы могли использовать очень простой цикл для создания текстового файла с записями для того каталога в каталоге:

for d in ~/Desktop/logs/* ; do zgrep -E '/Jan/2016' "$d"/* >"$d"/out.txt ; done

Desktop/logs
├── first_folder
│  ├── access_log
│  ├── access_log.gz
│  └── out.txt
└── second_folder
    ├── access_log
    ├── access_log.gz
    └── out.txt

Используя эту небольшую корректировку сценария waltinator:

for d in ~/Desktop/logs/* ; do
    if [[ -d "$d" ]] ; then
        outname="$d".txt
        find "$d" -type f -print0 | xargs -0 zgrep -E '/Jan/2016' >"$outname"
    fi
done

даст эту структуру:

├── first_folder
│   ├── access_log
│   └── access_log.gz
├── first_folder.txt
├── second_folder
│  ├── access_log
│  └── access_log.gz
└── second_folder.txt

Примечания

  • for d in ~/Desktop/logs/* ; do цикл по содержанию ~/Desktop/logs и сделайте что-то с ними
  • if [[ -d "$d" ]]; then сделайте что-то только если $d каталог
  • find "$d" -type f -print0 ищите в каталогах $d для файлов и вывода их с пустым разделителем так, чтобы мы могли использовать
  • xargs -0 создайте команду с выводом предыдущей команды как аргументы, с помощью нулевого символа в качестве разделителя (в других отношениях имена файлов с пробелами повреждают этот подход),
  • zgrep поиски в архивировали/сжали архивы
3
ответ дан 1 December 2019 в 13:24

Современный способ использовать find, принимая во внимание, что Вы будете в конечном счете видеть, что имя файла содержит пробелы, с -print0 и xargs -0:

# list all filenames containing '/Jan/2016'
find ~/Desktop/logs -type f -print0 | xargs -0 zgrep -l '/Jan/2016'
# 1. Have all the data from all folders that contain that string under one text file
find ~/Desktop/logs -type f -print0 | xargs -0 zgrep -l '/Jan/2016' >one.text.file
#
# 2. Have data that contains string in a separate text files depending on a folder (example: first folder - first.txt etc)
pushd ~/Desktop/logs
for dir in * ; do
    if [[ -d "$dir" ]] ; then
        outname="$dir.txt"
        find "~/Desktop/logs/$dir" -type f -print0 | xargs -0 zgrep -l '/Jan/2016' >"$outname"
    fi
done
popd
4
ответ дан 1 December 2019 в 13:24

Другие вопросы по тегам:

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