我正在一个小型项目中,我以这种方式显示了压缩日志:
youyou.log
youyou.log.1.gz
youyou.log.2.gz
youyou.log.3.gz
我必须解压缩它们的位置,然后将它们从最高索引合并到youyou.log
问题是,有时我可能只有一个文件,有时甚至更多,但是未知它可能会持续到youyou.log.n.gz
我开始写一些可以工作的东西,但是一点都不优雅。 我假设有一定数量的.gz文件,但给出了一些错误,稍后我会忽略。
main.sh
#!/bin/bash
gunzip *.gz
cat youyou.log.7 youyou.log.6 youyou.log.5 youyou.log.4 youyou.log.3 .log.2 youyou.log.1 youyou.log > youyou_complete.log
然后像这样忽略:
main.sh > /dev/null 2>&1
请问有更好的方法来解决这个问题吗?谢谢
答案 0 :(得分:1)
请尝试以下操作:
find . -name "youyou.log.*.gz" -maxdepth 1 | sort -rn -t. -k4 | xargs zcat | cat - youyou.log > youyou_complete.log
它假定您没有提前解压缩*.gz
文件。
[说明]
find . -name "youyou.log.*.gz" -maxdepth 1
查找具有指定名称的文件
当前目录中的模式,然后创建一个列表,例如:
./youyou.log.1.gz
./youyou.log.2.gz
./youyou.log.3.gz
[snip]
./youyou.log.9.gz
./youyou.log.10.gz
sort -rn -t. -k4
首先将传递的文件名分隔在“。”上,
那么内部列表将类似于:
(null) /youyou log 1 gz
(null) /youyou log 2 gz
(null) /youyou log 3 gz
[snip]
(null) /youyou log 9 gz
(null) /youyou log 10 gz
-k4
选项告诉sort
将文件名列表按第4位排序
列(1、2、3,..)。 -n
选项指定数字排序
和-r
选项使比较结果相反。
现在,关注列表已发送到xargs
命令的标准输入:
./youyou.log.10.gz
./youyou.log.9.gz
[snip]
./youyou.log.3.gz
./youyou.log.2.gz
./youyou.log.1.gz
xargs
创建一个命令,该命令由以下参数组成
通过从标准输入中读取的参数。
然后该命令将如下所示:
zcat ./youyou.log.10.gz ./youyou.log.9.gz ... ./youyou.log.1.gz
zcat
解压缩文件列表并写入未压缩的数据
通过按参数顺序合并数据来实现标准输出。
最终命令cat - youyou.log
连接标准输入,并且
然后按指定顺序youyou.log
将结果重定向到
youyou_complete.log
。
如果您的sort
支持-z
选项,最好这样说:
find . -name "youyou.log.*.gz" -maxdepth 1 -print0 | sort -z -rn -t. -k4 | xargs -0 zcat | cat - youyou.log > youyou_complete.log
-print0
选项告诉find
使用空字符\0
作为分隔符
文件名列表而不是换行符。 -z
的{{1}}选项和
sort
的{{1}}选项与之合作。-0
错误地将参数列表拆分给它们。这可能不
在给定的示例中发生,因为文件名显然没有
包含空格,但是这种考虑可能有用
使脚本更加安全和面向未来(IMHO)。答案 1 :(得分:0)
以下是使用Python的示例
import os
path = "/home/user/logs/"
listOfFiles = os.listdir(path)
mainFile = open("youyou.log.complete", "a")
for file in listOfFiles:
os.system("gunzip ", file)
listOfUnzipped = os.listdir(path)
for file in listOfUnzipped:
secondaryFile = open(file, "r")
text = secondaryFile.read()
mainFile.write(text)
mainFile.write("\r\n")
secondaryFile.close()
mainFile.close()
答案 2 :(得分:0)
touch tmp.log
gzip -c tmp.log > tmp.log.gz
for i in $(dir -r *.gz); do
cat $i >> tmp.log.gz
done
gunzip tmp.gz
cat youyou.log >> tmp.log
我还没有测试它,虽然代码可以自我解释。
我唯一担心的是,如果您有名称为.gz
等的日志文件,则dir
的输出youyou.log.11, youyou.log.22
的文件顺序。
答案 3 :(得分:0)
棘手的部分是按降序获取文件,您的说明还不清楚,这是什么意思。例如,如果您有youyou.log.32和youyou.log.4-应该先哪个?如果您对严格的字符顺序感兴趣,可以使用ls
来获得适当排序的列表(具有ls
的所有陷阱),即
# bash
cat $(ls -r youyou.log.[0-9]*) >youyou.complete.log
或者您可以从bash切换到zsh,在其中可以通过排序完成文件名的生成。 示例:
# zsh
cat youyou.log.[0-9]*(On) >youyou.complete.log
(On)
的名称降序排列。这将在youyou.log.4之后对youyou.log.32进行排序。如果您可以安排日志文件具有适当的时间戳记,则使用(Om)
而不是(On)
将对修改时间进行降序排序。
如果您没有时间戳,但是想对文件进行“数字”排序,即youyou.log.32比youyou.log.4早,因为4小于32,这是我能想到的最佳解决方案将使用sort
:
# bash
cat $(echo youyou.log.[0-9]*|fmt -w 1|sort -n -r -t. -k 3) >youyou.complete.log
fmt
确保每行有一个 youyou 文件,而sort
在第三个字段(-k 3)上按数字(-n)排序,其中字段分隔符是句点(-t。)。