Unix shell 脚本 - 使用 /bin/sh shell 查找以前的日期
Posted
技术标签:
【中文标题】Unix shell 脚本 - 使用 /bin/sh shell 查找以前的日期【英文标题】:Unix shell scripting - Finding a previous date using /bin/sh shell 【发布时间】:2015-08-26 11:42:39 【问题描述】:我正在编写一个 shell 脚本,它检索一个目录中的所有文件,这些文件是 x 天前最后一次修改的,从当天 00:00 开始。
我为此使用的当前查找命令如下所示,但这将从脚本运行时开始检查。例如。如果脚本在 12:00 运行并检索到所有在 7 天或更早之前修改的文件,则所有在 7 天前12:00之后修改的文件将不包含在内在查找结果中。
find $SEARCH_DIR -mtime +$DAYS_AGO
我知道在 Bash 中您可以使用 -daystart 和 find 来克服这个问题,但是脚本需要在使用 -daystart 的 IBM z/OS 机器上运行strong>/bin/sh shell,不支持此选项。
我见过其他情况,人们使用 touch 创建文件并使用 date -d 或 date 将时间戳更改为所需日期 --日期 如下所示,但这些选项再次对我不开放这个shell。
date -d '7 days ago'
date --date '3 months 1 day ago'
此 PDF 显示了我们的 IBM z/OS 版本支持的 UNIX 命令的完整列表:http://publibfp.dhe.ibm.com/epubs/pdf/bpxza5c0.pdf
有人对如何克服这个问题有任何想法吗?任何建议将不胜感激。
提前致谢!
【问题讨论】:
find
(或者,就此而言,date
)的功能与您使用的 shell 无关。也许您可以在 z/OS 机器上安装 GNU findutils。 (您也可以安装 Bash,但如上所述,它对解决这个问题没有帮助。)
感谢@tripleee,但我不认为安装 GNU findutils 对我来说是一个选择。
【参考方案1】:
This page 显示了多种符合 POSIX 标准的方法来获取自纪元以来的当前秒数。最简单的使用awk
,它使用当前时间作为默认的随机数种子:
epoch_time=$(awk 'BEGIN srand(); print srand() ' < /dev/null)
从这里,您可以算术操作当前时间:
# 7 days ago
ts=$(( epoch_time - 7 * 24 * 60 * 60 ))
“3 个月,1 天”之类的东西会很棘手,因为 GNU 对一个月的定义仅仅是“与今天相同,但在前一个月,因此不能轻易将其转换为固定的秒数.
【讨论】:
【参考方案2】:试试这个find . -mmin $(($(date +"%s") % (60*60*24) / 60 + 7*24*60))
解释:
date +"%s" #get current unix time_stamp
$(date +"%s") % (60*60*24) / 60 #get minutes offset from day start
$(($(date +"%s") % (60*60*24) / 60 + 7*24*60))
#get minutes offset from day start of 7 days ago
find . -mmin $(($(date +"%s") % (60*60*24) / 60 + 7*24*60))
#-mmin file’s data was last modified n minutes ago.
【讨论】:
感谢@luoluo 的快速回复。不幸的是,在我的 shell 版本中,%s 似乎不是 date 的有效格式。还有其他方法可以获得当前的 UNIX 纪元时间吗? 可惜。你可以自己实现一个date %s
来获取当前的UNIX纪元时间。
@IainDuff 如果您可以提供一个指向您所拥有的 find 等版本的手册页的 URL,这将有所帮助。例如,如果你有 perl,对于 date +%s
,你可以使用 perl -e 'print time;'
感谢@meuh,我现在已链接到问题中所有受支持的 UNIX 命令。我确实考虑过 perl,但我们的系统也不支持它。【参考方案3】:
在过去的美好时光里,我们通过操纵时区进行了一些简单的日期运算。 你需要找到你的TZ是什么,然后你可以抵消它24小时回到1天, 等等。 (这在较新的系统上不能超过 24 小时)。
为了简化,假设我们在 TZ=GMT0。然后在午夜查找超过 1 天的文件:
date=`TZ=GMT24 date +%Y%m%d`
touch -t $date0000 reffile
find $SEARCH_DIR ! -newer reffile ...
让我们知道 TZ=GMT48 是否可以将日期向后移动 2 天,依此类推。
您的问题确实是 shell 脚本,但是您可以求助于编译一些 C 语言吗?
这个小程序将获取一个文件名并将其修改时间移回午夜
前一天的。将-1
更改为天数。然后你可以创建一个文件,
用这个程序“解除”它,并使用find ... ! -newer file
。
/* reset time modified to 1 day back midnight */
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <sys/time.h>
#include <time.h>
#include <stdlib.h>
pexit(char *s)
perror(s);
exit(1);
main(int argc,char **argv)
char *file;
struct stat buf;
time_t timeoff = -1L*24*60*60; /* one day back */
struct timeval tvp[2];
struct tm *tmp;
if(argc!=2)pexit("usage: file to untouch. not ");
file = argv[1];
if(lstat(file,&buf)<0)pexit("cannot lstat file");
tmp = localtime(&buf.st_mtime);
timeoff -= tmp->tm_sec+(tmp->tm_min+tmp->tm_hour*60)*60; /* midnight */
tvp[0].tv_sec = buf.st_atime;
tvp[0].tv_usec = 0;
tvp[1].tv_sec = buf.st_mtime + timeoff;
tvp[1].tv_usec = 0;
if(utimes(file, tvp)<0)pexit("cannot change time");
【讨论】:
谢谢@meuh。不幸的是,它似乎无法超过 24 小时(TZ=GMT48 似乎被视为 TZ=GMT0,如 date +%Y%m%d 只返回当前日期)。 如果可以编译,我添加了一个小 C 程序来取消修改文件。 @IainDuff 也许是因为缺少标志:试试TZ=GMT+48 date
和TZ=GMT-48 date
。以上是关于Unix shell 脚本 - 使用 /bin/sh shell 查找以前的日期的主要内容,如果未能解决你的问题,请参考以下文章