头图
最近在使用 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) },
  });
});

可惜它是按照文件的修改时间排序的。

结论

目前,无法按照创建时间排序。

你遇到过这样的问题吗?你用的什么解决方法?欢迎来讨论。


来了老弟
508 声望31 粉丝

纸上得来终觉浅,绝知此事要躬行