测试文件是否在文件名中的日期之后被修改

Pet*_*ill 12 osx bash timestamps files

YYYYMMDD在文件名中有一个名为 with的文件,例如

file-name-20151002.txt
Run Code Online (Sandbox Code Playgroud)

我想确定这个文件是否在 2015-10-02 之后被修改过。

笔记:

  • 我可以通过查看 的输出来做到这一点ls,但我知道解析 的输出ls是一个坏主意。
  • 我不需要查找特定日期之后的所有文件,只需要一次测试一个特定文件。
  • 我不担心文件在我创建后的同一天被修改。也就是说,我只想知道这个20151002名称中的文件是否在 2015 年 10 月 3 日或之后被修改过。
  • 我在 MacOs 10.9.5 上。

cas*_*cas 9

以下脚本将检查命令行上指定的所有文件的日期:

它需要的GNU版本seddatestat

$ cat check-dates.sh 
#! /bin/bash

for f in "$@" ; do
  # get date portion of filename
  fdate=$(basename "$f" .txt | sed -re 's/^.*(2015)/\1/')

  # convert it to seconds since epoch + 1 day
  fsecs=$(echo $(date +%s -d "$fdate") + 86400 | bc )

  # get modified timestamp of file in secs since epoch
  ftimestamp=$(stat -c %Y "$f")

  [ "$ftimestamp" -gt "$fsecs" ] && echo "$f has been modified after $fdate"
done

$ ./check-dates.sh file-name-20151002.txt 
file-name-20151002.txt has been modified after 20151002
$ ls -l file-name-20151002.txt 
-rw-rw-r-- 1 cas cas 0 Oct 26 19:21 file-name-20151002.txt
Run Code Online (Sandbox Code Playgroud)

这是一个未经测试的版本,但如果我正确阅读了在线手册页,它应该可以在 Mac(以及 FreeBSD 等)上运行:

#! /bin/bash

for f in "$@" ; do
  # get date portion of filename
  fdate=$(basename "$f" .txt | sed -e 's/^.*\(2015\)/\1/')

  # convert it to seconds since epoch + 1 day
  fsecs=$(echo $(date -j -f %Y%m%d "$fdate" +%s) + 86400 | bc )

  # get modified timestamp of file in secs since epoch
  ftimestamp=$(stat -f %m "$f")

  [ "$ftimestamp" -gt "$fsecs" ] && echo "$f has been modified after $fdate"
done
Run Code Online (Sandbox Code Playgroud)

  • @cas:对 Thomas 评论的一个相当严厉的回复,我相信这只是改进您的解决方案的建议......在现实世界中,拥有“最标准的可能”脚本不仅是一种奖励,而且是必要的(或而是强制性的)。许多地方无法安装 GNU 版本的工具(我碰巧知道 3 个不同的地方,其中某些系统的最新版本 bash 是 2.x,而 awk 太旧了,与原始版本非常非常接近)。这个问题的需求可能不是“关键”(但可能是),也不会经常被其他人寻求/使用,但总的来说,拥有一个可移植的解决方案是一个+ (6认同)
  • 然后随意编写您自己的版本。我写我想写的,而不是你想让我写的……这包括使用 GNU 版本的工具。IMO,GNU **是**事实上的标准。以及使用中的 linux 发行版与非 linux、非 gnu *nixes 的相对数量支持这一点。 (2认同)

don*_*sti 5

以下是一些可能的方法:

  • OSX stat:

    newer () {
    tstamp=${1:${#1}-12:8}
    mtime=$(stat -f "%Sm" -t "%Y%m%d" "$1")
    [[ ${mtime} -le ${tstamp} ]] && printf '%s\n' "$1 : NO: mtime is ${mtime}" || printf '%s\n' "$1 : YES: mtime is ${mtime}"
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • GNU date:

    newer () {
    tstamp=${1:${#1}-12:8}
    mtime=$(date '+%Y%m%d' -r "$1")
    [[ ${mtime} -le ${tstamp} ]] && printf '%s\n' "$1 : NO: mtime is ${mtime}" || printf '%s\n' "$1 : YES: mtime is ${mtime}"
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • zsh仅有的:

    zmodload zsh/stat
    newer () {
    tstamp=${1:${#1}-12:8}
    mtime=$(zstat -F '%Y%m%d' +mtime -- $1)
    [[ ${mtime} -le ${tstamp} ]] && printf '%s\n' "$1 : NO: mtime is ${mtime}" || printf '%s\n' "$1 : YES: mtime is ${mtime}"
    }
    
    Run Code Online (Sandbox Code Playgroud)

用法:

较新的文件

输出示例:

file-name-20150909.txt : YES: mtime is 20151026
Run Code Online (Sandbox Code Playgroud)

或者

file-name-20151126.txt : NO: mtime is 20151026
Run Code Online (Sandbox Code Playgroud)