直接运行 ls -l 时,文件会按名称字母顺序排列;目录一长,五分钟前刚改过的文件就可能淹没在列表中。本文介绍如何使用 ls -t、-r、-u、-c 和 find,按修改时间、访问时间、变更时间和创建时间正确排序。
查看目录内容,是在任何 Linux 服务器上最先做的事情之一,而 ls 通常是大家顺手使用的命令。不过默认情况下,ls 会按文件名进行字母排序。这对小型主目录没有问题,但当你打开 /etc 或 /var/log,想快速找出最近变更的文件时,这种方式就不太好用了。
在实际系统管理工作中,这种需求非常常见:软件包更新后服务停止运行,你希望查明刚刚改动过哪些配置文件;备份任务每晚执行,脚本需要挑出最新的归档;日志目录里堆着数百个轮转文件,而你只关心当前正在写入的那一个。
ls 可以通过一个选项按时间排序,而且它不只支持最后修改时间,还能按多种不同的时间戳排序。只要弄清每个选项读取的是哪一个时间戳,找出任意目录中最新的或最旧的文件就只需要几秒钟。
Linux 如何记录文件时间戳
在按时间排序之前,先弄清楚 Linux 实际为文件保存哪些时间会很有帮助。ls 的每个排序选项读取的时间戳并不相同,一旦选错,输出顺序看起来就可能毫无规律。
每个文件都会在 inode(磁盘上保存文件元数据的小型记录)中保存以下时间戳:
mtime(修改时间):文件内容发生变化时更新。这是ls -l默认显示的时间。atime(访问时间):文件被读取时更新;不过大多数系统只会不定期更新,后文会进一步说明。ctime(变更时间):文件元数据发生变化时更新,例如权限、所有者或名称改变;文件内容发生变化时也会更新。它不是创建时间,这一点经常被混淆。btime(创建时间):记录文件创建时刻,前提是文件系统支持,例如 ext4、XFS 和 Btrfs。
要一次查看这四种时间,最简单的方法是使用 stat 命令。下面以 /etc/hosts 为例:
stat /etc/hosts
输出:
File: /etc/hosts
Size: 268 Blocks: 8 IO Block: 4096 regular file
Device: 252,1 Inode: 1310834 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2026-11-02 08:55:10.412367219 +0530
Modify: 2026-10-28 14:03:22.180415667 +0530
Change: 2026-10-28 14:03:22.180415667 +0530
Birth: 2026-09-14 11:20:47.904112031 +0530
你系统上的大小、inode 编号和设备行会有所不同,因此应重点查看最下面四行时间。如果 Birth 显示为短横线(-),说明该文件所在的文件系统或内核没有提供这个文件的创建时间。
访问时间还需要额外注意。大多数 Linux 发行版默认以 relatime 选项挂载文件系统。这意味着,只有当旧访问时间早于文件的修改时间或变更时间,或者旧访问时间已经超过 24 小时,内核才会更新 atime。这样可以避免每次读取都产生一次磁盘写入,但也意味着同一个下午读取文件两次,并不会让它在访问时间排序中跳到最前面。
读懂 ls -l 输出中的日期和时间列
现在你已经知道存在哪些时间戳,接下来看看 ls 在哪里显示它们,因为后面的每个排序示例都需要正确读取这一列。
-l 选项用于输出长格式列表,其中包括权限、硬链接数、所有者、所属组、大小、修改时间和名称:
ls -l /etc/nginx
输出:
total 68
drwxr-xr-x 2 root root 4096 Feb 9 2026 conf.d
-rw-r--r-- 1 root root 1125 Dec 1 2023 fastcgi.conf
-rw-r--r-- 1 root root 1055 Dec 1 2023 fastcgi_params
-rw-r--r-- 1 root root 2837 Dec 1 2023 koi-utf
-rw-r--r-- 1 root root 2223 Dec 1 2023 koi-win
-rw-r--r-- 1 root root 5465 Dec 1 2023 mime.types
drwxr-xr-x 2 root root 4096 Feb 9 2026 modules-available
drwxr-xr-x 2 root root 4096 Feb 9 2026 modules-enabled
-rw-r--r-- 1 root root 1446 Dec 1 2023 nginx.conf
-rw-r--r-- 1 root root 180 Dec 1 2023 proxy_params
-rw-r--r-- 1 root root 636 Dec 1 2023 scgi_params
drwxr-xr-x 2 root root 4096 Sep 23 12:13 sites-available
drwxr-xr-x 2 root root 4096 Apr 19 2026 sites-enabled
drwxr-xr-x 2 root root 4096 Sep 23 12:13 snippets
-rw-r--r-- 1 root root 664 Dec 1 2023 uwsgi_params
-rw-r--r-- 1 root root 3071 Dec 1 2023 win-utf
注意,有些行显示 12:13 这样的具体时间,另一些行则显示 2026 这样的年份。GNU ls 会为最近六个月内修改过的文件显示时分,对更早的文件改为显示年份。因此,Dec 01 2023 只是说明文件足够旧,所以省略了具体时间。示例 3 会演示如何始终显示完整时间戳。
按时间排序 ls 输出的实用示例
理解时间戳和日期列之后,就可以开始排序了。下面的示例会逐层递进,从日常使用的 ls -lt 一直讲到整个目录树的排序。
示例 1:使用 ls -lt 按修改时间排序
-t 选项指示 ls 按时间排序,最新的文件排在最前面,默认使用修改时间。再配合 -l,这就是查看 /etc 等目录最近有哪些变化的最快方法,特别适合在软件包更新或配置改动导致故障后排查问题。
由于 /etc 中有数百个条目,可以把输出传给 head,只显示前几行:
ls -lt /etc | head -n 6
输出:
total 1092
-rw-r--r-- 1 root root 95381 Nov 2 09:12 ld.so.cache
drwxr-xr-x 3 root root 4096 Nov 2 09:11 nginx
drwxr-xr-x 2 root root 4096 Nov 2 09:11 alternatives
-rw-r----- 1 root shadow 1302 Nov 1 18:40 shadow
-rw-r--r-- 1 root root 2914 Nov 1 18:40 passwd
第一行 total 表示所列文件占用的磁盘空间,单位为 1K 块。因此 head -n 6 会输出这一行以及最新的五个条目。在这个示例中,可以看到 nginx 目录中的内容在 09:11 发生过变化,而 passwd 和 shadow 在前一天晚上发生了变化,这通常意味着新增或修改了用户账户。
也可以用更易读的长格式选项 --sort=time 写出同样的排序,这种方式适合交给其他人阅读的脚本:
ls -l --sort=time /etc | head -n 6
示例 2:使用 ls -ltr 让最新文件排在最后
第一个示例把最新文件放在顶部,配合 head 很方便;但在包含数百个文件的目录中,输出顶部可能已经滚出屏幕。加上 -r 可以反转顺序,让最新文件排在最下方、紧挨着命令提示符,无需向上滚动就能看到。
这可能是服务器上最常用的命令形式之一,尤其在日志目录中:
ls -ltr /var/log
输出:
...
-rw-r----- 1 syslog adm 184322 Nov 2 08:30 auth.log.1
drwxr-xr-x 2 root root 4096 Nov 2 09:05 nginx
-rw-r----- 1 syslog adm 48210 Nov 2 09:18 auth.log
-rw-r----- 1 syslog adm 912644 Nov 2 09:20 syslog
最后几行显示的是当前正在写入的文件,排查正在发生的故障时,可以据此判断应该先打开哪个日志。
示例 3:使用 --full-time 显示完整日期和时间
前面已经看到,ls -l 会隐藏较旧文件的具体时分,而且从不显示秒。若两个文件在同一分钟内发生修改,或者需要把文件时间与日志中的时间戳对应起来,这种精度就不够用了。
--full-time 选项会打印完整日期、精确到纳秒的时间以及时区偏移,而且可以与 -t 一起使用:
ls -lt --full-time /etc/nginx
输出:
total 64
-rw-r--r-- 1 root root 1477 2026-11-02 09:11:37.551209183 +0530 nginx.conf
drwxr-xr-x 2 root root 4096 2026-10-28 14:10:02.118540871 +0530 conf.d
drwxr-xr-x 2 root root 4096 2026-10-28 14:10:02.118540871 +0530 sites-available
drwxr-xr-x 2 root root 4096 2026-10-28 14:10:02.118540871 +0530 sites-enabled
-rw-r--r-- 1 root root 1125 2026-04-14 10:02:18.000000000 +0530 fastcgi.conf
-rw-r--r-- 1 root root 1055 2026-04-14 10:02:18.000000000 +0530 fastcgi_params
由软件包安装的文件通常会显示 .000000000,因为软件包只把时间保存到秒。如果完整纳秒时间戳过于冗长,可以用 --time-style 选择更短的格式。例如 long-iso 会输出便于排序的日期和时分,但不包含秒:
ls -lt --time-style=long-iso /etc/nginx
输出:
total 64
-rw-r--r-- 1 root root 1477 2026-11-02 09:11 nginx.conf
drwxr-xr-x 2 root root 4096 2026-10-28 14:10 conf.d
示例 4:按访问时间、变更时间或创建时间排序
到目前为止,每个示例都在按修改时间排序。前面通过 stat 见到的其他时间戳也很有价值,例如你想知道目录中哪些脚本最近确实被执行过,或者哪些文件的权限发生过变化。
可以把以下选项与 -l 和 -t 组合使用:
-u:显示访问时间,替代默认的修改时间;同时使用-t时会按访问时间排序。单独与-l使用时,它只显示访问时间,仍然按名称排序,所以记得加上-t。-c:以相同方式处理变更时间(ctime)。在执行chmod或chown但没有改动文件内容之后,这个选项很有用。--time=birth:在文件系统和内核支持的情况下,按创建时间排序并显示该时间。
例如,要查看 /usr/local/bin 中哪些脚本最近被读取过,可以按访问时间排序:
ls -ltu /usr/local/bin
要查找 Web 根目录中最近更改过权限或所有者的文件,可以改为按变更时间排序:
ls -ltc /var/www/html
由于前面介绍的 relatime 行为,访问时间顺序只能作为大致参考,不能视为每次读取的精确记录。
示例 5:在脚本中获取最新的文件或目录
前面的示例主要面向屏幕阅读,但按时间排序在脚本中同样有用。一个常见场景是备份目录:夜间任务会写入新的归档,而另一个脚本只需要复制或验证最新的归档。
由于 -t 会把最新文件排在前面,取输出的第一行就能得到最近的归档:
latest=$(ls -t /srv/backups/*.tar.gz | head -n 1)
echo "Latest backup: $latest"
输出:
Latest backup: /srv/backups/web-2026-11-02.tar.gz
同样的思路也适用于目录。-d 选项让 ls 列出目录本身而不是其内容,*/ 模式又只匹配目录,因此可以查看最近修改过的是哪个项目目录:
ls -ltd /srv/projects/*/
请注意,只有在文件名完全受你控制时才适合解析 ls 输出,例如上面带有日期名称的备份文件。如果文件名中包含换行符,结果就会被破坏,因此下一个示例在无法确定文件名格式时会改用 find。
示例 6:使用 find 跨子目录按时间排序
此前的每个示例都只对单个目录中的文件排序。如果对目录树运行 ls -ltR,ls 仍会分别对各个子目录排序,所以你无法看出整棵树中最后变化的是哪个文件。
这时应使用 find,因为它的 -printf 选项能以可排序格式输出每个文件的修改时间。%T+ 指令会输出 YYYY-MM-DD+HH:MM:SS 格式的时间,按纯文本排序也能得到正确顺序;%p 则输出路径:
sudo find /var/log -type f -printf '%T+ %p\n' | sort -r | head -n 5
输出:
2026-11-02+09:20:14.5521378870 /var/log/syslog
2026-11-02+09:20:14.1189022310 /var/log/journal/8f3c2a.../system.journal
2026-11-02+09:18:41.7703315260 /var/log/auth.log
2026-11-02+09:05:12.3341908870 /var/log/nginx/access.log
2026-11-02+08:30:00.9921045310 /var/log/nginx/error.log
这里使用 sudo,是因为一些日志目录只允许 root 或 adm 组读取;如果不加 sudo,find 会输出 Permission denied 并跳过这些目录。sort -r 把最新文件放到最前面,head -n 5 则只保留整棵目录树中最近的五个文件。
如果你只需要找出最近一段时间内发生变化的文件,而不是完整排序,find /etc -type f -mmin -60 会列出 /etc 下过去 60 分钟内修改过的所有文件。这通常是回答“刚才那次更新到底改了什么”的最快方法。
日常使用 ls 时间排序的技巧
现在你已经可以按任意时间戳排序了。养成几个小习惯,可以让这些命令更快,也能避免一些令人困惑的结果。
如果你每天要输入很多次 ls -ltr,可以在 ~/.bashrc 中添加一个短别名。额外的 -h 选项会用 1.2M 这样的单位显示大小,而不是原始字节数,使列表更容易浏览:
echo "alias lt='ls -ltrh'" >> ~/.bashrc
source ~/.bashrc
比较不同服务器上的时间时,请记住 ls 显示的是服务器本地时区的时间。如果一台服务器使用 UTC,另一台使用 IST,同一时刻可能显示为相差五个半小时。为单条命令设置 TZ 变量,可以按 UTC 显示时间,便于直接比较:
TZ=UTC ls -lt --full-time /etc/nginx
较新的 Ubuntu 版本默认使用 Rust 编写的 uutils coreutils 提供 ls,而 Rocky Linux、AlmaLinux 和 RHEL 使用 GNU coreutils。对于日常排序,本文中的选项在两者上的行为相同,但精确输出空格等细节可能不同。因此在脚本中依赖这些输出之前,应先在自己的系统上核对结果。
最后,如果你刚复制了一个文件,却看到它保留着旧的修改时间,这是正常现象。cp -p、rsync -a 以及解压 tar 等操作会有意保留原始修改时间,因此该文件会按内容最后变更的时间排序,而不是按文件到达服务器的时间排序。它的 ctime 则会显示复制时间,这正是 ls -ltc 能给出答案的另一种场景。
总结
现在,你可以使用 ls -t 配合 -u、-c 或 --time,按修改时间、访问时间、变更时间或创建时间对任意目录列表排序;使用 -r 反转顺序;使用 --full-time 显示精确时间戳。
要查看整棵目录树,可以组合使用 find 的 -printf '%T+ %p\n' 与 sort,一次找出所有子目录中最新变化的文件。










