如何在许多 gz/常规文件中查找包含特定字符串的日志并将其保存为一个或多个 txt 文件?

如何在许多 gz/常规文件中查找包含特定字符串的日志并将其保存为一个或多个 txt 文件?

2016 年 9 月 22 日的新问题,如下所示!

我的路径如下所示:

~/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

文件确实非常大,有好几 GB。

输出:

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 (2016 年 9 月 22 日)

我需要修改/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?

尽管所有文件都已创建,但并非所有结果都会返回到创建的文件中。

答案1

find考虑到您最终会看到包含空格的文件名,现代的使用方式是使用-print0xargs -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

答案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在压缩档案中搜索

相关内容