Contents

检查文件的年龄和修改时间

1. 概述

在本教程中,我们将介绍如何在 Linux 中检查文件的年龄和修改时间。首先,我们将通过 Linux 的 EXT 文件系统提供的文件的不同时间戳。之后,我们将介绍可用于检查文件修改时间及其相对于修改时间的年龄的各种方法和实用程序。

2. Linux中文件的不同时间戳

在 Linux 上创建文件时,文件的元数据会附加三个不同的时间戳。当我们访问或修改文件时,这些时间戳会发生变化。目前,专为 Linux 内核开发的扩展文件系统 (EXT) 上没有文件创建时间戳。出于这个原因,我们将使用修改时间或更改时间来根据年龄过滤文件。因此,年龄将与修改时间相关。

对于支持文件创建时间的其他文件系统,我们可以使用一些命令,例如stat

2.1. 修改时间

修改后的时间戳包含文件数据被更改的时间。这意味着当我们对文件的实际内容进行更改时,文件系统会更新修改时间。

我们可以通过运行带有*-l*选项的ls 来检查修改时间:

$ ls -l
-rwxr-xr-x 1 hey hey 20879 Dec 12 21:44 README.md

2.2. 访问时间

访问的时间戳包含上次读取文件时的时间戳。换句话说,文件被引用了,但内容和元数据没有被修改。我们还应该知道,**如果我们修改文件的内容,文件的访问时间也会更新,*因为修改文件需要先访问文件。 我们可以使用ls命令的-u*选项来查看文件的访问时间:

$ ls -lu
-rwxr-xr-x 1 hey hey 20879 Dec 12 21:50 README.md

2.3. 更改时间

**更改的时间戳包含文件元数据的更改时间。**例如,如果我们更改文件的权限或更改其文件名,文件系统将更新其更改时间。

我们可以将*-c选项传递给ls*以显示更改的时间:

$ ls -lc
-rwxr-xr-x 1 hey hey 20879 Dec 12 21:57 README.md

3. 使用find工具

对于这些时间戳,我们可以分别使用带有*-mmin*、-amin和*-cmin选项的find 工具,根据文件的修改、访问或更改时间来搜索文件。**我们可以在 shell 脚本中使用find*,因为与其他工具相比,它可以更容易地根据 Linux 文件层次结构中的时间戳查找文件。**

让我们在我们的主目录中找到一些在过去一小时内被修改过的文件:

$ find ~ -mmin 60
./github/libri
./github/libri/README.md

同样,我们也可以根据访问时间过滤掉文件。让我们看看过去 10 分钟内访问了哪些文件:

$ find ~ -amin 10
./libri/.git/objects/bf
./libri/.git/logs
./libri/.git/logs/refs
./libri/.git/logs/refs/remotes
...

或者我们可以根据更改的时间查找文件。在这种情况下,让我们查找一个多小时前更改的文件:

$ find ~ -cmin +60
./libri
./libri/README.md

4. 使用 date实用程序查找文件的年龄

我们可以使用date 实用程序获得文件修改时间的更细粒度的时间戳。我们可以使用date实用程序的**-r或*–reference*选项来指定文件:

$ date -r ./README.md "+%s"
1639330559

date命令的最后一个参数是打印时间戳的格式。在我们的例子中,我们告诉日期以秒为单位打印自 UNIX 纪元以来的时间,即 1970 年 1 月 1 日午夜 00:00:00,UTC 时间。所有文件时间戳都以 UNIX Epoch 格式存储,我们可以使用它来创建不同的时间和日期格式。

要获取当前时间的 Epoch,我们可以简单地使用date命令后跟 Epoch 格式:

$ date +%s
1639332063

我们可以使用这个数字通过从当前 Epoch 中减去文件修改的 Epoch 来查找文件的年龄

#!/bin/sh
[ "$#" -eq 0 ] && echo "Usage: file-age <file>" && exit 1
filepath=$1
echo "$(basename $filepath): $(($(date +%s) - $(date -r "$filepath" +%s))) seconds"

该脚本需要一个文件作为参数。所以,让我们喂它一个并检查一下:

$ ./file-age ./README.md
README.md: 958 seconds

5. 使用stat命令

作为date命令的替代,我们还可以使用stat命令。stat 命令打印出有关文件和文件系统的信息。

让我们看看它的实际效果:

$ stat README.md
  File: README.md
  Size: 20879     	Blocks: 48         IO Block: 4096   regular file
Device: 8,3	Inode: 17301783    Links: 1
Access: (0755/-rwxr-xr-x)  Uid: ( 1000/     hey)   Gid: ( 1000/     hey)
Access: 2021-12-12 19:56:47.653310645 +0500
Modify: 2021-12-12 22:35:59.056320075 +0500
Change: 2021-12-12 22:35:59.056320075 +0500
 Birth: -

正如我们所看到的,它打印了很多关于文件的额外信息。我们还可以注意到上面输出中的Birth字段,它应该暗示文件的创建时间。虽然它应该在支持文件出生时间的其他文件系统上工作,但它在 EXT 文件系统上不受支持。

在 ZFS、BTRFS 和 XFS 等其他文件系统上,我们可以检查文件的诞生时间:

$ stat -c %w /mnt/zfs_drive/test.txt
2021-12-12 23:30:00.190003029 +0500

-c选项指定格式。在我们的例子中,我们将*%w*参数传递给选项,它表示人类可读的出生时间。

此外,我们还可以使用*%Y*格式打印自 Epoch 以来修改后的时间戳:

$ stat -c %Y README.md
1639330559

有关格式的完整列表,我们可以参考stat手册页

6. 使用perl

每个 Linux 发行版都安装了perl 。我们可以使用单行perl命令来获取文件的修改年龄:

$ perl -l -e 'print -M $ARGV[0], " days"' "/etc/ftab"
82.8740162037037 days

让我们分解一下:

  • -l命令启用换行符
  • -e命令执行单引号内的单行
  • -M选项告诉pring以天 为单位打印文件的修改时间
  • perl命令的最后一个参数是我们要处理的文件