dir
有两个常规文件。
file1
有abc\n
,file2
有def\n
。用gzip压缩这两个文件,如下图,
#ls
#echo 'abc\n' > file1
#echo 'def\n' > file2
#gzip file1
#gzip file2
#ls
file1.gz file2.gz
在我抓取内容后,
#find . -type f -name "*.gz" -exec zgrep -Iq . \{} \; -exec zcat \{} \;
def\n
abc\n
我没有按照文件创建时间的顺序获取文件的内容。预期输出应始终为abc\ndef\n
.
有趣的观察:实际输出有时,def\nabc\n
有时abc\ndef\n
问题:
如何按时间戳顺序(递减/递增)查找文件?
答案1
报告的文件顺序find
对用户来说是不透明的。它可以是它们在目录中出现的顺序。一些find
实现通过 inode 编号或其他标准对它们进行重新排序,以尝试提高性能。改变顺序的唯一方法是通过-depth
谓词告诉find
处理/输出在它们所在的分支之前离开。
作为 的替代方案find
,您可以使用zsh
的递归 glob 功能:
zgrep whatever ./**/*.gz(D.Om)
globOm
限定符按最后修改时间排序(最旧的在前)。.
仅适用于常规文件(相当于find
's -type f
),D
包括find
默认情况下隐藏的(点)文件。
如果你得到一个arg 列表太长错误,您可以使用zargs
:
autoload -U zargs # best in ~/.zshrc
zargs ./**/*.gz(D.Om) -- zgrep whatever
使用bash
(或任何支持 Ksh 样式进程替换的 shell)和最新的 GNU 工具,等效项将是:
xargs -r0a <(
export LC_ALL=C
find . -type f -name '*.gz' -printf '%T@\t%p\0' |
sort -zn | cut -zf2-) zgrep whatever
答案2
一种选择是输出文件时间戳以及文件路径,按其排序,然后将其删除:
find -type f -name "*.gz" -printf '%C@\t%p\n'|sort -nk1|cut -f2-|xargs zcat
请注意,如果您的文件名可能包含潜在不安全的字符(例如空格),只需替换
xargs zcat
和
xargs -d "\n" zcat
如果您需要适应文件名中的换行符,则可以使用空字节来终止记录,如 @stéphane-chazelas 答案中详细说明(通过这在实践中很少会出现问题)。
答案3
不幸的是,find 命令的工作方式不能保证输出按字母顺序或文件年龄时间顺序排列。你可以尝试这样的事情:
ls -1dtr $(find . -maxdepth 1 -type f -name '*.gz') | xargs gzcat $1