3

我正在尝试做我认为在 Linux 下很简单的事情。我有一个运行各种测试程序的 bash 脚本,我想确定当前目录中的哪些文件是由测试程序创建的。所以我正在做这样的事情:

触摸时间戳文件
运行测试
查找 -newer 时间戳文件 -type f > 文件列表
rm -f 时间戳文件

原来 find -newer 的粒度很差,所以通常发生的情况是测试程序生成的一些文件显示为比时间戳文件更旧。所以我尝试了这个:

ls -tr1 | sed '1,/时间戳文件/d'

生成相同的列表。这通常有效,但并非总是如此。我仍然会遇到测试生成的文件显示为比时间戳文件更旧的情况。

谢谢!

PS我可以通过拍摄目录的两个快照来完成此操作,一个是在测试程序运行之前,一个是之后,然后比较它们。第二个列表中不在第一个列表中的任何文件都必须由测试程序创建(我不关心后台作业或其他用户写入目录)。但是这种方法不是我想要的,因为如果在运行测试之前没有删除输出文件(它们应该是,但在某些情况下可能不是),这种方法会说它不是由测试程序,因为它在运行测试程序之前就在目录中。

4

4 回答 4

3

您实际上可以使用 touch 将目录中所有当前文件的时间戳强制为过去,例如:

touch -t 200801010000.00 *

find -newer如果您在运行测试之前执行此操作,那么 " " 拾取它的时间应该有足够的差异。如果粒度是两分钟,您可以将所有当前文件设置为十分钟前,时间戳文件设置为 5 分钟前,然后运行您的测试。

所以你的脚本变成:

touch -t (current time - 10 minutes) *
touch -t (current time -  5 minutes) timestamp-file
run the test
find -newer timestamp-file -type f > list-of-files
rm -f timestamp-file

假设您已经安装了一个不错的 Perl,您可以执行以下操作以在 5 分钟前(或使用 -600 10 分钟)以正确的格式获取“ date -t”:

use Date::Manip;
print UnixDate(DateCalc(ParseDateString("now"),"-300"),"%Y%m%d%H%M.%S") . "\n";

如果由于某种原因不允许您更改时间戳,请使用:

sleep 300
touch timestamp-file
sleep 300
run the test
find -newer timestamp-file -type f > list-of-files
rm -f timestamp-file

它具有相同的效果,但让你有十分钟的时间去喝咖啡(如果你不是喝咖啡的人,你可以选择毒药)。

于 2009-01-02T23:35:16.763 回答
2

如果您考虑如何find(1)实施,就会很清楚为什么有时这可能无法按您的预期工作。这里有一个提示:

  $ touch timestamp ; touch newer ; find . -newer timestamp 
  $ rm timestamp newer
  $ touch timestamp ; sleep 1 ; touch newer ; find . -newer timestamp
  .
  ./newer
  $

find(1)使用系统调用获取文件 mtime/ctime/atime 值stat(2)。以下是struct statfrom <sys/stat.h>(Linux) 的元素:

  time_t    st_atime;   /* time of last access */
  time_t    st_mtime;   /* time of last modification */
  time_t    st_ctime;   /* time of last status change */

在 Linux(通常是 unices)time_t上是一个整数,表示“从 1970 年开始的秒数”。所以-newer能领悟到的最细粒度也不过是一秒而已。

于 2009-01-03T10:18:01.893 回答
1

在运行之前获取所有文件的文件名,但包括它们的时间戳:

find -printf '%p %T@\n' | sort > file1

如果您没有可用的 find 选项,您也可以使用 stat 来完成该工作:

find -print0 | xargs -0 stat -c "%n %Y" | sort > file1

并且跑到之后file2。然后使用

comm -1 -3 file1 file2

它会向您显示唯一的行file2,如果我没记错的话,这些行必须是新文件。如果它们以前存在,它们的修改时间将会改变,这由%T@东西来处理(打印出自 1970 年以来的秒数):

[js@HOST2 cpp]$ find -printf '%p %T@\n' | 排序>文件1
[js@HOST2 cpp]$ echo foo>bar
[js@HOST2 cpp]$ echo foo>baz
[js@HOST2 cpp]$ find -printf '%p %T@\n' | 排序>文件2
[js@HOST2 cpp]$ comm -1 -3 file1 file2
. 1230947309.0000000000
./bar 1230947308.0000000000
./baz 1230947309.0000000000
./file2 1230947315.0000000000
[js@HOST2 cpp]$ find -printf '%p %T@\n' | 排序>文件1
[js@HOST2 cpp]$ echo lol>bar
[js@HOST2 cpp]$ find -printf '%p %T@\n' | 排序>文件2
[js@HOST2 cpp]$ comm -1 -3 file1 file2
./bar 1230947359.0000000000
./file2 1230947362.0000000000
[js@HOST2 cpp]$`
于 2009-01-03T01:32:18.290 回答
0

为什么不创建一个临时目录来运行测试?在目录上使用基于时间戳的名称来帮助跟踪何时发生的结果,并在完成后简单地删除整个目录。

于 2009-01-02T23:47:37.753 回答