【问题标题】:Determining age of a file in shell script在shell脚本中确定文件的年龄
【发布时间】:2009-06-09 11:08:18
【问题描述】:

生日,

我需要查看 sh shell 脚本中的特定文件是否超过 58 分钟。我说的是带有一些 POSIX 扩展的纯香草 Solaris shell。

我想过做一个

touch -t YYYYMMDDHHmm.SS /var/tmp/toto

时间戳是 58 分钟前,然后做一个

find ./logs_dir \! -newer /var/tmp/toto -print

我们需要对使用镜像从各种服务器检索到的一些日志文件进行后处理。等待文件稳定是该团队决定镜像是否完成的方式,因此当天的日志现在已完成并准备好处理。

任何建议都非常感谢。

干杯,

【问题讨论】:

    标签: unix shell file


    【解决方案1】:

    我需要一些东西来测试特定文件的年龄,而不是经常重新下载。所以使用GNU datebash

    # if file's modtime hour is less than current hour:
    [[ $(date +%k -r GPW/mstall.zip) -lt $(date +%k) ]] && \
    wget -S -N \
    http://bossa.pl/pub/metastock/mstock/mstall.zip \
    

    更新——这个版本对我来说效果更好,而且更准确、更容易理解:

    [[ $(date +%s -r mstall.zip) -lt $(date +%s --date="77 min ago") ]] && echo File is older than 1hr 17min
    

    BSD 变体(在 Mac 上测试)是:

    [[ $(stat -f "%m" mstall.zip) -lt $(date -j -v-77M +%s) ]] && echo File is older than 1hr 17min
    

    【讨论】:

    • 第二个版本非常优雅(清晰)地使用了 date(1) 命令,代码不错!
    • --date 可以缩写为 -d 为简洁起见。 (要求每个人都知道-d 是什么。这里每个人都知道。)
    【解决方案2】:

    你可以在find命令中使用不同的单位,例如:

    find . -mtime +0h55m
    

    将返回所有修改日期早于 55 分钟的文件。

    【讨论】:

    • find 有一个 -mmin 谓词,例如。 -mmin +58
    • 这取决于 find 的版本。也许你可以在一个真正的新版本中做到这一点,或者 Mac 或其他东西,但我的大多数 Linux 机器上的 GNU Find 4.2 需要“-mtime”以 24 小时为增量。
    • 这在哪里工作?在我的 (find (GNU findutils) 4.7.0) 上,我试试这个并把 find: invalid argument +0h55m' 变成 -mtime'
    【解决方案3】:

    这是一个老问题,抱歉,但为了其他人像我一样寻找一个好的解决方案......

    我能想到的最好方法是使用find(1) 命令,这是我所知道的唯一可以直接测试文件年龄的 Un*x 命令:

    if [ "$(find $file -mmin +58)" != "" ]
    then
      ... regenerate the file ...
    fi
    

    另一个选项是使用stat(1) 命令以秒为单位返回文件的年龄,并使用 date 命令以秒为单位返回现在的时间。结合 bash shell 数学运算符计算文件的年龄变得非常容易:

    age=$(stat -c %Y $file)
    now=$(date +"%s")
    if (( (now - age) > (58 * 60) ))
    then
        ... regenerate the file ...
    fi
    

    您可以在没有这两个变量的情况下执行上述操作,但它们会使事情变得更清晰,就像使用 bash 数学(也可以被替换)一样。多年来,我在脚本中广泛使用了 find(1) 方法,并推荐它,除非你真的需要以秒为单位知道年龄。

    【讨论】:

    • 上面@Marcos 答案中的 date -r 用法也很好,我第一次读到这里就错过了。
    • @tommy.carstensen :这是 GNU stat(来自 GNU coreutils 包),您也可以在 Mac 上安装它(例如使用 brew)。至于选项:-c 等价于--format,后面必须跟想要的格式参数,在这种情况下,%Y 是最后一次数据修改时间的格式,(自纪元以来的秒数)。官方文档位于:gnu.org/software/coreutils/stat(或man stat
    【解决方案4】:

    其中一部分可能是使用stat。您可以通过-r-s 来获取所有文件元数据的可解析表示。

    find . -print -exec stat -r '{}' \;
    

    AFAICR,第 10 列将显示 mtime。

    【讨论】:

    • 我没有看到 POSIX/SUS 规定的 stat(1),但 BSD 肯定有。并非所有的选项开关都与 GNU 相同,但这不足为奇。
    • Mac OS X 上的第 9 列。您可以通过对文件执行 stat -s 来确认这一点。
    【解决方案5】:

    由于您要测试特定文件的时间,您可以先使用test 并将其与您专门创建的文件进行比较:

    test /path/to/file -nt /var/tmp/toto
    

    或:

    touch -t YYYYMMDDHHmm.SS /var/tmp/toto
    if [/path/to/file -nt /var/tmp/toto]
       ...
    

    【讨论】:

      【解决方案6】:

      您也可以使用 ls 和 awk 来获得所需的内容。 awk 有一个 c-ish printf,它允许你以任何你想要的方式格式化列。

      我在 linux 上的 bash 和 solaris 上的 ksh 中对此进行了测试。

      选择各种选项,为您的应用程序获得最佳价值。尤其是 bash 中的“--full-time”和 ksh 中的“-E”。

      重击

      ls -l foo | awk '{printf "%3s %1s\n", $6, $7}'

      2011-04-19 11:37

      ls --full-time foo | awk '{printf "%3s %1s\n", $6, $7}'

      2011-04-19 11:37:51.211982332

      ksh

      ls -l bar | awk '{printf "%3s %1s %s\n", $6, $7, $8}'

      5 月 3 日 11:19

      ls -E bar | awk '{printf "%3s %1s %s\n", $6, $7, $8}'

      2011-05-03 11:19:23.723044000 -0400

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-05-11
        • 1970-01-01
        • 1970-01-01
        • 2011-05-05
        • 1970-01-01
        • 2018-05-19
        相关资源
        最近更新 更多