2011-12-22 60 views
-1

我需要编写一个Linux shell脚本,它可以扫描根目录并打印上次执行后修改的文件。Shell脚本在上次执行后修改后打印文件?

例如,如果文件A昨天执行并且我今天修改它,shell脚本必须打印文件A.但是,如果文件B昨天执行并且我还没有修改它,则不应该打印文件B 。

+2

请饶树! – 2011-12-22 18:38:07

回答

2

您的主要问题是跟踪文件何时执行。

问题是,Linux并没有单独跟踪文件的执行时间,而是为了其他目的(例如备份或审阅)而读取文件时,因此它将非常棘手。

有各种各样的技巧可以考虑,但他们都不是特别微不足道或邀请。一种选择可能是启用流程会计。另一个可能是修改每个脚本以记录它的执行时间。

的“上次访问的时间(或atime,或st_atime,基于字段的名称struct stat包含的信息)不帮你,因为,如前所述,每当读取文件被修改。尽管执行文件肯定会被访问,但可能会有许多读取访问不执行文件,但会触发访问时间的更新。

有了这些注意事项,访问时间可能是最好的,你的脚本需要查找访问时间等于修改时间的文件(这意味着文件被修改了并且自修改以来一直未被访问 - 既未被读取,也未被打印也未被执行过。这并不完美,但它可能是最好的近似,但缺乏复杂的执行跟踪系统。

一旦你有一个机制来跟踪文件的执行时间,那么你可以设计一个适当的方法来确定自上次执行文件以来哪些文件被修改了。

+0

它在'atime'中(但并不完美 - 读取文件也会设置'atime',就像执行它一样)。 http://www.brandonhutchinson.com/ctime_atime_mtime.html – Amadan 2011-12-22 18:47:28

0

在shell中很难做到这一点,仅仅是因为在shell中很难以合理的格式获得atimemtime。考虑程序移动到一个功能更全面的语言如Ruby或Perl:

ruby -e 'puts Dir["**/*"].select{ |file| File.mtime(file) > File.atime(file) }' 

使用**/*在当前目录下的所有文件下面,**/*.rb在当前目录下的所有Ruby脚本在下面,/*所有文件中根...你得到的模式。

请注意我在@JohanthanLeffer的评论中写道:UNIX不区分读取文件和执行文件。因此,就本程序而言,使用cat ./script打印脚本将具有与使用./script执行脚本相同的效果。没有办法区分我能想到的阅读和执行,而不是制作自己的内核。

但是,在大多数情况下,您可能不会阅读可执行文件;如果你编辑它们,保存会在打开后出现,所以mtime仍然会胜过atime。唯一不好的情况是,如果你在编辑器中打开一个文件,然后退出而不保存它(或者只是用less查看它,不作修改)。只要你避免这种情况,该方法就可以工作。

另外请注意,大多数编辑者实际上不会修改文件,而是创建一个新文件并复制旧文件中的内容,然后用新文件覆盖旧文件。这不设置mtime,但是ctime。如果这是您的使用模式,请相应地修改脚本。

编辑:显然,stat可以帮助明智的表示。这是bash

#!/bin/sh                 

for FILE in `find .`; do 
    if [ `stat -f "%m -gt %a" $FILE` ]; then 
    echo $FILE 
    fi 
done 

更换"find ."(与反引号)与*只是当前目录,或/*根。要使用ctime而不是mtime,请使用%c而不是%m

0

Unix系统中存储的任何文件3个时间值:

  1. 上次访问
  2. 最后修改
  3. 最后的修改。

我不认为你可以得到最后的执行时间没有使用一些人为的手段,如创建一个日志或临时文件等当一个可执行文件运行。

PS:请记住,并非Unix中的每个文件都是一个可执行文件,所以这可能是他们从未想过要存储文件last execution timestamp的原因。

但是,如果你想获得这些时间值,则使用:

stat -c "%X" file-name # to get last accessed time value as seconds since Epoch 
stat -c "%Y" file-name # to get last modified time value as seconds since Epoch 
stat -c "%Z" file-name # to get last change time value as seconds since Epoch 
相关问题