【问题标题】:Unix shell scripting - Finding a previous date using /bin/sh shellUnix shell 脚本 - 使用 /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 中您可以使用 -daystartfind 来克服这个问题,但是脚本需要在使用 -daystart 的 IBM z/OS 机器上运行strong>/bin/sh shell,不支持此选项。

我见过其他情况,人们使用 touch 创建文件并使用 date -ddate 将时间戳更改为所需日期 --日期 如下所示,但这些选项再次对我不开放这个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 对我来说是一个选择。

标签: shell date unix sh zos


【解决方案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 ${date}0000 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 dateTZ=GMT-48 date
    猜你喜欢
    • 2011-11-14
    • 2023-04-09
    • 2012-05-22
    • 2013-01-29
    • 2011-02-27
    • 2010-09-05
    • 2016-03-18
    相关资源
    最近更新 更多