最近在使用 Node.js 的 fs.readdir 遇到一个问题,就是想让读出的文件按创建时间的先后排序。最后结论是,办不了!!!。下面记录一下研究的过程。
场景还原
有下面这样一个网页应用,读取的是服务器上的文件,fs.readdir 读取到的文件列表是按 文件的修改时间 排序的,并不是按创建时间,如果你有强迫症,这个刚好戳中了你的“G”点。
如果我们修改了第一个文件夹的名称,或者在它内部新增了文件,那么它就会跑到最后一个。(ps:但是我他么就想按最开始的顺序排列啊!!)
那么,我们不能按照文件创建时间排序吗?
windows 与 linux 的文件创建时间
在windows系统上,一个文件有3个时间属性,他们分别是
创建时间
修改时间
访问时间
linux上的文件也有三个时间属性,分别是
访问时间(access time 简写为 atime)
修改时间(modify time 简写为mtime)
状态修改时间(change time 简写为ctime)
很多人误将linux系统上文件的ctime 对标成windows系统上的创建时间,这是不对的,ctime里的字母c是change的缩写而非create的缩写。当文件的元数据发生变化时,ctime就会发生改变,比如文件的权限,拥有者,所属的组,硬链接,当然也包括文件内容发生变化。
所以,在linux系统上,无法获得文件的创建时间了么?这是一个复杂的问题,关于linux系统上为什么不记录文件的创建时间,有很多的讨论,有人认为文件的创建时间对于大多数人来说是无用的,可以用其他来代替:
如果文件没有修改过,就等于mtime,即最后一次write时间
如果文件没有被修改权限过,就等于ctime,即最后一次使用chmod的时间
如果文件没有被读取过,就等于atime,即最后一个read的时间
但是呢,总感觉有点鸡肋。
在 stackoverflow 上找到一个方法,自己把读取到的文件列表排序:
return new Promise((resolve, reject) => {
fs.readdir(dir, (err, items) => {
if (err) return reject(err);
const files = [];
items.forEach((item) => {
const info = fs.lstatSync(path.join(dir, item));
const h = m.encode(path.resolve(dir, item));
files.push({
name: item,
extension: info.isDirectory() ? 'directory' : item.split('.').pop().toLowerCase(),
hash: h,
size: info.size,
is_dir: info.isDirectory(),
time: info.mtime.getTime()
});
});
resolve({
success: true,
data: { tree: files.sort((a, b) => a.time - b.time) },
});
});
可惜它是按照文件的修改时间排序的。
结论
目前,无法按照创建时间排序。
你遇到过这样的问题吗?你用的什么解决方法?欢迎来讨论。