我有一个文件名中带有 的文件YYYYMMDD
,例如
file-name-20151002.txt
我想确定是否这文件于2015年10月2日后修改。
笔记:
- 我可以通过查看 的输出来做到这一点
ls
,但我知道解析 的输出ls
是一个坏主意。 - 我不需要寻找全部日期在特定日期之后的文件,只需测试一一次指定一个文件。
- 我不担心文件在创建后的同一天被修改。也就是说,我只想知道
20151002
名称中的这个文件是否在2015年10月3日或更晚的时间被修改过。 - 我使用的是 MacO 10.9.5。
答案1
以下脚本将检查命令行上指定的所有文件的日期:
它需要 GNU 版本的sed
、date
和stat
$ 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
这是一个未经测试的版本,但如果我正确阅读了在线手册页,应该可以在 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
答案2
以下是一些可能的方法:
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}" }
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}" }
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}" }
用法:
较新的文件
输出示例:
file-name-20150909.txt : YES: mtime is 20151026
或者
file-name-20151126.txt : NO: mtime is 20151026
答案3
使用 bash 和stat
来expr
获取数字形式的日期并进行比较:
#!/bin/bash
for file
do moddate=$(stat -f %m -t %F "$file") # MacOS stat
moddate=${moddate//-/} # 20151026
if filedate=$(expr "$file" : '.*-\([0-9]*\).txt')
then if [ $moddate -gt $filedate ]
then echo "$file: modified $moddate"
fi
fi
done
这是我之前针对 Linux 的回答。
#!/bin/bash
for file
do moddate=$(stat -c %y "$file")
moddate=${moddate%% *} # 2015-10-26
moddate=${moddate//-/} # 20151026
if [[ "$file" =~ ([0-9]{8}).txt$ ]]
then if [[ $moddate > ${BASH_REMATCH[1]} ]]
then echo "$file: modified $moddate"
fi
fi
done
bash=~
正则表达式运算符将文件名的 8 位数字捕获到 bash 数组 BASH_REMATCH 中。[[ ]]
比较字符串,尽管您只是将它们作为数字进行比较,而不是在[ -gt ]
.
答案4
另一种zsh
方法:
zmodload zsh/stat # best in ~/.zshrc or
zmodload -F zsh/stat +b:zstat # to avoid overriding an eventual
# system stat command.
setopt extendedglob # best in ~/.zshrc
ls -ld -- **/*[0-9](#c8)*(De@'zstat -F %Y%m%d -A m +mtime $REPLY &&
[[ ${(SM)${REPLY:t}#[0-9](#c8)} != $m ]]'@)
将报告名称中看起来像时间戳但与上次修改时间不对应的文件。
zsh
有大量类似的运算符来操作全局变量和变量。快速(并且通常可靠)完成任何工作非常方便,但很难完全理解所有工作,并且通常会产生我们通常所说的结果只写代码(难以辨认的代码的委婉说法,但也意味着您在命令提示符下编写单次使用时不需要阅读它)
快速浏览一下:
**/pattern(qualifier)
:带有 glob 限定符的递归 glob。[0-9](#c8)
匹配8位数字。这就是 zsh Extendedglob 等价于ksh
s的内容{8}([0-9])
。D
: 包含隐藏文件e@...@
: 这评估glob 限定符运行一些文本来进一步限定文件。传入的文件路径$REPLY
zstat...
检索数组中格式为 YYYYMMDD 的 mtime$m
。${REPLY:t}
: 扩展到t文件的 tail (基本名称)。${(SM)something#pattern}
。提取匹配的部分图案从某物。那些S
(Substring 搜索)和M
(扩展为中号附着部分)被称为参数扩展标志。