Bash新手求助:如何按多组Unix时间戳查找目录修改文件
解决多时间区间文件查找的问题
嘿,作为Bash新手碰到这种跨多组时间区间的文件查找需求,确实容易卡壳,我给你分享几个实用的解决方案:
方案1:用find直接处理Unix时间戳(推荐,性能更好)
其实你可能不知道,GNU find是支持Unix时间戳的!只要在时间戳前加上@符号,就能让-newermt参数识别它。比如-newermt @1609459200就代表“修改时间晚于该Unix时间戳对应的时刻”。
针对多组时间区间,我们可以把每组区间转换成\( -newermt @起始时间 ! -newermt @结束时间 \)的条件,然后用-o(逻辑或)把所有区间条件连接起来。
假设你的CSV文件times.csv格式是每行一个区间(起始时间戳,结束时间戳),比如:
1609459200,1612137600 1614556800,1617235200
可以用awk生成对应的find条件,再传给find执行:
find /path/to/target-dir -type f \( $(awk -F',' '/^[0-9]+,[0-9]+$/ {printf " -newermt @%s ! -newermt @%s -o", $1, $2}' times.csv | sed 's/ -o$//') \)
细节解释:
awk -F',' '/^[0-9]+,[0-9]+$/:只处理格式正确的行,避免空行或错误格式干扰printf " -newermt @%s ! -newermt @%s -o", $1, $2:为每个区间生成find条件片段,末尾加-o表示“或”sed 's/ -o$//':去掉最后一个多余的-o,避免语法错误- 外层的
\( ... \):确保所有区间条件作为一个整体,和find的其他参数(比如-type f)正确结合
如果需要包含结束时间戳的文件,可以把结束时间戳加1,比如把awk里的$2改成$2+1,这样! -newermt @(end+1)就会包含刚好在end时间戳的文件。
方案2:兼容性更强的stat+awk组合
如果你的系统是比较老的版本,find不支持@时间戳格式,那就用stat先获取文件的修改时间戳,再用awk过滤:
find /path/to/target-dir -type f -print0 | xargs -0 stat -c "%Y %n" | awk -F' ' -v intervals="$(cat times.csv)" ' BEGIN { # 把CSV里的所有区间读入数组 split(intervals, arr, "\n") for (i in arr) { if (split(arr[i], range, ",") == 2) { starts[i] = range[1] ends[i] = range[2] } } } # 检查每个文件的时间戳是否落在任意区间 { for (i in starts) { if ($1 >= starts[i] && $1 <= ends[i]) { print $2 next } } }'
细节解释:
-print0和xargs -0:处理包含空格、特殊字符的文件名,避免拆分错误stat -c "%Y %n":输出文件的Unix时间戳(修改时间)和文件名- awk部分:先把所有时间区间存入数组,再逐个检查每个文件的时间戳是否符合条件
注意事项
- 性能差异:方案1直接在
find层面过滤文件,大目录下速度更快;方案2需要遍历所有文件的stat结果,适合兼容性优先的场景 - 区间边界:根据需求调整时间戳的边界处理,比如是否包含结束时间点
- CSV格式:确保CSV每行是纯数字的时间戳对,避免多余空格或注释
内容的提问来源于stack exchange,提问作者Dan Parker
相关产品推荐
相关产品推荐

