如果上次执行后修改过,则打印文件的 Shell 脚本?

发布于 2024-12-22 07:47:26 字数 138 浏览 0 评论 0原文

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

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

I need to write a Linux shell script which can scans a root directory and prints files which were modified after they were last executed.

For example, if File A executed yesterday and I modify it today, the shell script must print File A. However, if File B executed yesterday and I don't modify it yet, then file B shouldn't be printed.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

醉态萌生 2024-12-29 07:47:26

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

问题是,Linux 不会单独跟踪文件的执行时间和出于其他目的(例如备份或查看)而读取文件的时间,因此执行起来会非常棘手。

可以考虑的技巧有很多种,但没有一个是特别微不足道或特别吸引人的。一种选择可能是启用进程记帐。另一种可能是修改每个脚本以记录其执行时间。

“上次访问”时间(或 atimest_atime,基于包含信息的 struct stat 中的字段名称)对您没有帮助,因为正如已经指出的,每当读取文件时它就会被修改。尽管肯定会访问已执行的文件,但可能存在许多不执行该文件但确实触发访问时间更新的读访问。

有了这些注意事项,访问时间可能是您能做的最好的事情,并且您的脚本需要查找访问时间等于修改时间的文件(这意味着文件已被修改且尚未被修改)自修改后就被访问 - 既不读取也不打印也不执行)。它并不完美,但如果缺少复杂的执行跟踪系统,它可能是可用的最佳近似值。

一旦建立了跟踪文件执行时间的机制,您就可以设计一种适当的方法来确定哪些文件自上次执行以来已被修改。

Your primary problem is tracking when the files were executed.

The trouble is, Linux does not keep separate track of when a file was executed as opposed to when it was read for other purposes (such as backup, or review), so it is going to be extremely tricky to get going.

There are a variety of tricks that could be considered, but none of them are particularly trivial or inviting. One option might be to enable process accounting. Another might be to modify each script to record when it is executed.

The 'last accessed' time (or atime, or st_atime, based on the name of the field in struct stat that contains the information) doesn't help you because, as already noted, it is modified whenever the file is read. Although an executed file would certainly have been accessed, there may be many read accesses that do not execute the file but that do trigger an update of the access time.

With those caveats in place, it may be that the access time is the best that you can do, and your script needs to look for files where the access time is equal to the modify time (which means the file was modified and has not been accessed since it was modified - neither read nor printed nor executed). It is less than perfect, but it may be the best approximation available, short of a complex execution tracking system.

Once you've got a mechanism in place to track the execution times of files, then you can devise an appropriate means of working out which files were modified since they were last executed.

书间行客 2024-12-29 07:47:26

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

  1. 最后访问
  2. 最后修改
  3. 最后更改。

我认为如果不使用一些人为手段(例如在可执行文件运行时创建日志或临时文件等),您就无法获得最后执行时间。

PS:请记住,Unix 中并非每个文件都是可执行文件,因此这可能就是他们从未想过存储文件的上次执行时间戳的原因。

但是,如果您确实想获取这些时间值,请使用:

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

Unix system stores 3 time values for any file:

  1. last access
  2. last modification
  3. last change.

I don't think you can get last execution time without using some artificial means, like creating a log or temp file etc. when a executable file runs.

PS: Remember not every file in Unix is an executable so that's the reason probably they never thought of storing a file's last execution timestamp as well.

However if you do want to get these time values then use:

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
满栀 2024-12-29 07:47:26

在 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 ." (带反引号)替换为 * 仅当前目录,或 /* 为 root。要使用 ctime 而不是 mtime,请使用 %c 而不是 %m

It is very hard to do this in shell, simply because it is very hard to get atime or mtime in a sensible format in shell. Consider moving the routine to a more full-featured language like Ruby or Perl:

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

Use **/* for all files in current directory and below, **/*.rb for all Ruby scripts in current directory in below, /* for all files in root... you get the pattern.

Take note what I wrote in a comment to @JohanthanLeffer: UNIX does not differentiate between reading a file and executing it. Thus, printing the script out with cat ./script will have the same effect as executing it with ./script, as far as this procedure is concerned. There is no way to differentiate reading and executing that I can think of, short of making your own kernel.

However, in most cases, you probably won't read the executables; and if you edit them, the save will come after opening, so mtime will still trump atime. The only bad scenario is if you open a file in an editor then exit without saving it (or just view it with less, without modification). As long as you avoid this, the method will work.

Also make note that most editors will not actually modify a file, but create a new file and copy the contents from the old one, then overwrite the old one with the new one. This does not set the mtime, but ctime. Modify the script accordingly, if this is your usage pattern.

EDIT: Apparently, stat can help with the sensible representation. This is in bash:

#!/bin/sh                                                                   

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

Replace "find ." (with backticks) with * for just current directory, or /* for root. To use ctime instead of mtime, use %c instead of %m.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文