Ale*_*lls 14 stat timestamps files
我正在创建一个通用的编译/转译系统。了解文件是否已经编译/转译的一种方法是比较源文件和目标文件的修改日期。
我需要编写一个可以做到这一点的 bash 脚本:
source_file=foo;
target_file=bar;
stat_source=$(stat source_file);
stat_target=$(stat target_file);
Run Code Online (Sandbox Code Playgroud)
但是如何从统计输出中提取日期并进行比较?有没有比stat
比较文件的最近修改时间更好的方法?
如果我在日志文件上调用 stat ,我会得到:
16777220 12391188 -rw-r--r-- 1 alexamil staff 0 321 "Jun 22 17:45:53 2017" "Jun 22 17:20:51 2017" "Jun 22 17:20:51 2017" "Jun 22 15:40:19 2017" 4096 8 0 test.log
Run Code Online (Sandbox Code Playgroud)
AFAICT,时间粒度不超过秒。如果可能的话,我需要得到比这更细粒度的东西。
Tho*_*key 24
鉴于您使用的是stat
(类似的功能,但在 BSD 和 GNU 上的输出格式不同),您还可以使用该test
实用程序,它直接进行此比较:
FILE1 -nt FILE2
FILE1 is newer (modification date) than FILE2
FILE1 -ot FILE2
FILE1 is older than FILE2
Run Code Online (Sandbox Code Playgroud)
在你的例子中,
if [ "$source_file" -nt "$target_file" ]
then
printf '%s\n' "$source_file is newer than $target_file"
fi
Run Code Online (Sandbox Code Playgroud)
该功能在 POSIX 中不可用(请参阅 其文档test
),它提供了一个基本原理:
一些新发明的或来自 KornShell 的其他主要作为条件命令 ([[]]) 的一部分出现在早期提案中:s1
>
s2, s1<
s2, str = pattern, str != pattern, f1-nt
f2, f1-ot
f2, and f1 -ef f2。当从 shell 中删除条件命令时,它们没有被带入 test 实用程序中,因为它们没有包含在 sh 实用程序的历史实现中内置的 test 实用程序中。
尽管该功能得到广泛支持,但未来可能会发生变化。
请注意,当操作数是符号链接时,考虑的是符号链接目标的修改时间(这通常是您想要的,find -newer
如果不是,请改用)。当符号链接无法解析时,实现之间的行为(有些人认为现有文件总是比无法解析的文件新,如果任何操作数无法解析,有些人将始终报告错误)。
另请注意,并非所有实现都支持亚秒级粒度(从 4.4 版开始,bash
's test
/[
内置仍然不支持,例如,GNUtest
和test
内置的zsh
or ksh93
,至少在 GNU/Linux 上)。
以供参考:
test
实用程序实现(但请注意,您的 shell,如果fish
或类似 Bourne,也会有一个test
/[
内置函数,通常会隐藏它,使用env test
而不是test
绕过它),test.c 中的get_mtime读取struct timespec
,和-nt
使用该数据小智 4
在这个linux系统上进行测试。测试文件时间的常用方法是 shell:
[ file1 -nt file2 ] && echo "yes"
Run Code Online (Sandbox Code Playgroud)
似乎可以用秒来完成。这将以小于一秒的时间差接触文件,不会检测到该差异:
$ touch file2; sleep 0.1; touch file1; [ file1 -nt file2 ] && echo "yes"
Run Code Online (Sandbox Code Playgroud)
要确认问题(点后的时间为纳秒):
$ ls --time-style=full-iso -l file?
-rw-r--r-- 1 user user 0 2017-06-23 01:37:01.707387495 -0400 file1
-rw-r--r-- 1 user user 0 2017-06-23 01:37:01.599392538 -0400 file2
Run Code Online (Sandbox Code Playgroud)
比file1
. 稍微新一些file2
。
现在的问题是如何正确处理时间值。
一种解决方案是使用 ls 的格式化输出:
$ ls --time-style=+%s.%N -l file?
-rw-r--r-- 1 user user 0 1498196221.707387495 file1
-rw-r--r-- 1 user user 0 1498196221.599392538 file2
Run Code Online (Sandbox Code Playgroud)
将时间提取到两个变量(不带点):
$ file1time=$(ls --time-style=+%s%N -l file1 | awk "{print(\$6)}")
$ file2time=$(ls --time-style=+%s%N -l file2 | awk "{print(\$6)}")
Run Code Online (Sandbox Code Playgroud)
并比较时间(纳秒的时间勉强适合 64 位值。如果您的系统不使用 64 位,则此比较将失败):
$ [ $file1time -gt $file2time ] && echo "yes"
yes
Run Code Online (Sandbox Code Playgroud)
这表明它file1
比file2
如果ls
无法获得所需的格式,那么您可以尝试 stat。
$ stat file1
File: file1
Size: 0 Blocks: 0 IO Block: 4096 regular file
Device: 805h/2053d Inode: 9180838 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 1000/ user) Gid: ( 1000/ user)
Access: 2017-06-23 01:37:01.707387495 -0400
Modify: 2017-06-23 01:37:01.707387495 -0400
Change: 2017-06-23 01:37:01.707387495 -0400
Birth: -
Run Code Online (Sandbox Code Playgroud)
如果输出显示纳秒,我们将需要日期来解析(和格式化)时间。
$ stat --printf='%y\n' file1
2017-06-23 01:37:01.707387495 -0400
$ date +'%s%N' -d "$(stat --printf='%y\n' file1)"
1498196221707387495
Run Code Online (Sandbox Code Playgroud)
其余的都是一样的,将file1和file2的结果赋值给两个变量,并进行数值比较。
归档时间: |
|
查看次数: |
28343 次 |
最近记录: |