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
考虑到您最终会看到包含空格的文件名,现代的使用方式是使用-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
答案2
- 根据文件夹将包含字符串的数据放在单独的文本文件中(例如:第一个文件夹 - 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
在压缩档案中搜索