5

One of the properties of the fs.Stats object that is returned when one calls fs.stat is birthtime and birthtimeMs, which I'm assuming is when the file was created.

Stats {
  dev: 2114,
  ino: 48064969,
  mode: 33188,
  nlink: 1,
  uid: 85,
  gid: 100,
  rdev: 0,
  size: 527,
  blksize: 4096,
  blocks: 8,
  atimeMs: 1318289051000.1,
  mtimeMs: 1318289051000.1,
  ctimeMs: 1318289051000.1,
  birthtimeMs: 1318289051000.1,              // this value
  atime: Mon, 10 Oct 2011 23:24:11 GMT,
  mtime: Mon, 10 Oct 2011 23:24:11 GMT,
  ctime: Mon, 10 Oct 2011 23:24:11 GMT,
  birthtime: Mon, 10 Oct 2011 23:24:11 GMT } // and this value all the way down here

I'm wondering whether or not birthtime and birthtimeMs is used and reliably returned in UNIX or Linux and MacOS environments?

11
  • 2
    I can't give a concrete answer for OSX (although it certainly looks like it is supported through the BSD syscall), but as for Linux/Unix, I actually just ran across this issue with NodeJS and had to do a bunch of research to dig up answers - I wrote up a post here. Commented Oct 7, 2019 at 4:04
  • 1
    It depends not just on the OS, but on the FS, and quite possibly on some runtimes and libraries in between, and probably on OS versions and FS driver versions. And birthtime isn't the only one that's a problem as access time is often not fully implemented for security reasons, changed time and modified time are not consistently differentiated on non-Unixish OS+FS combos where they're not native, on some combos one of the unimplemented fields contains garbage rather than zero, and some combos abuse changed time to put birth time thinking either ctime means creation time, ... Commented Oct 7, 2019 at 4:46
  • 1
    ... that changed time is never used on the platform, or both. Node provides a way to query the OS but not a way for us to query which FS a file is on, so we can't use heuristics to decide, and there is no API in Node to query. Birth time as of some time in 2019 should now be fully propagated through all the layers to make it visible on FS's that support it. I think MacOS supported it because HFS did. I would expect most other Unixish OSs not to support it. I was looking into this for a toy project and have moved on so I don't recall the full details anymore. If you file a node bug I'll follow. Commented Oct 7, 2019 at 4:50
  • 1
    @JoshuaT It's just weird because even in the document you linked it says "On filesystems where birthtime is not available, this field holds the ctime instead." So it really doesn't answer the question definitively. Commented Oct 7, 2019 at 5:07
  • 1
    @hippietrail I'll let you know if I file bug. So is there another way to organize files and or directories by their creation date? Seems like such an essential task... Commented Oct 7, 2019 at 5:10

1 Answer 1

4

I'm also curios about this question, so I did a little experiment on macOS and Linux. Here are my observations.

First, create the file:

touch foo

Check the times, birth time is the same as others, which is expected.

> const fs = require("fs")
undefined
> fs.statSync("foo")
Stats {
  ...
  atimeMs: 1643199913195.383,
  mtimeMs: 1643199913195.383,
  ctimeMs: 1643199913195.383,
  birthtimeMs: 1643199913195.383,
  atime: 2022-01-26T12:25:13.195Z,
  mtime: 2022-01-26T12:25:13.195Z,
  ctime: 2022-01-26T12:25:13.195Z,
  birthtime: 2022-01-26T12:25:13.195Z
}

Update the file by echo:

echo bar > foo

Check again, mtime and ctime is updated, birth time remains the same, so far so good.

> fs.statSync("foo")
Stats {
  ...
  atimeMs: 1643199913195.383,
  mtimeMs: 1643199961947.3816,
  ctimeMs: 1643199961947.3816,
  birthtimeMs: 1643199913195.383,
  atime: 2022-01-26T12:25:13.195Z,
  mtime: 2022-01-26T12:26:01.947Z,
  ctime: 2022-01-26T12:26:01.947Z,
  birthtime: 2022-01-26T12:25:13.195Z
}

Edit the file with vi, then check again, something unexpected happens:

> fs.statSync("foo")
Stats {
  ...
  atimeMs: 1643199990663.3806,
  mtimeMs: 1643199990663.3806,
  ctimeMs: 1643199990667.3806,
  birthtimeMs: 1643199990663.3806,
  atime: 2022-01-26T12:26:30.663Z,
  mtime: 2022-01-26T12:26:30.663Z,
  ctime: 2022-01-26T12:26:30.667Z,
  birthtime: 2022-01-26T12:26:30.663Z
}

The birth time and all other times are all updated, it seems that a new file is created! After a little digging, I found out that vim is actually always copy backup files back and forth by default, so the btime is tampered. After I set set backupcopy=yse as instructed, btime is no longer updated.

> fs.statSync("foo")
Stats {
  ...
  atimeMs: 1643201126739.3442,
  mtimeMs: 1643201129323.3442,
  ctimeMs: 1643201129327.3442,
  birthtimeMs: 1643200860799.3528,
  atime: 2022-01-26T12:45:26.739Z,
  mtime: 2022-01-26T12:45:29.323Z,
  ctime: 2022-01-26T12:45:29.327Z,
  birthtime: 2022-01-26T12:41:00.799Z  // not the same as other times
}

It seems that birthtime is stable on macOS Monterey and Ubuntu with 4.15 kernel. But programs like vim which are using backup files will break the functionality, be aware of that.

According to an answer here, btime was added in Linux 4.11.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.