Skip to content

Instantly share code, notes, and snippets.

@bblfish
Last active October 24, 2021 09:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bblfish/629c0d7c9405c0979e60e73ea465664a to your computer and use it in GitHub Desktop.
Save bblfish/629c0d7c9405c0979e60e73ea465664a to your computer and use it in GitHub Desktop.
How does creating files and dirs change mod times
import java.io.{File, FileOutputStream, IOException}
import java.nio.file.*
import java.nio.file.attribute.*
import scala.collection.immutable.Map
trait Cache(var db: Map[Path, BasicFileAttributes]):
lazy val mod: Map[Path, FileTime] = db.view.mapValues(_.lastModifiedTime).toMap
val start = java.nio.file.Path.of(".")
def visitor(depth: Int) = new SimpleFileVisitor[Path] with Cache(Map[Path, BasicFileAttributes]()):
var level = 0
override
def preVisitDirectory(f: Path, attrs: BasicFileAttributes): FileVisitResult =
if level < depth then
level = level + 1;
db = db.updated(f, attrs)
FileVisitResult.CONTINUE
else FileVisitResult.SKIP_SUBTREE
override
def visitFile(file: Path, attrs: BasicFileAttributes): FileVisitResult =
if attrs.isDirectory && level >= depth
then FileVisitResult.SKIP_SUBTREE
else
db = db.updated(file, attrs)
FileVisitResult.CONTINUE
end visitor
def diff[P](db1: Map[Path, P], db2: Map[Path, P]): Map[Path, P] =
(db1.toSet diff db2.toSet).toMap
class Act(action: => Unit):
def doit(): Unit = action
def write(file: File, txt: String): Unit =
val out = new FileOutputStream(file)
out.write(txt.getBytes)
out.close
@main
def test =
import java.io.*
val visitors = LazyList.continually(visitor(3))
val actions = LazyList(
new Act(File("hello.txt").createNewFile()),
new Act(File("hi.txt").createNewFile()),
new Act(write(File("hi.txt"),"Hello World!")),
new Act(File("blog/comments").mkdirs()),
new Act(File("blog/blog1.html").createNewFile),
new Act(write(File("blog/blog1.html"),"Great post")),
new Act(File("blog/blog2.html").createNewFile),
new Act(File("blog/comments/GreatPost").createNewFile),
new Act(File("blog/comments/GreatPost").delete)
)
val history: List[Cache] = actions.zip(visitors).map { (act, v) =>
act.doit()
Thread.sleep(2000) // to make it easier to see the time stamps
Files.walkFileTree(start, v)
v
}.toList //we exec it now
history.sliding(2, 1) foreach {
case head :: tail :: Nil => println(diff(tail.mod, head.mod))
case _ => println("end")
}
@bblfish
Copy link
Author

bblfish commented Oct 1, 2021

Running the above on MacOS Monterey beta 7, with JDK17 in the Scala 3 console I get this output

scala> test
Map(. -> 2021-10-01T11:28:40.238122945Z, ./hi.txt -> 2021-10-01T11:28:40.238107489Z)
Map(./hi.txt -> 2021-10-01T11:28:42.244564896Z)
Map(./blog -> 2021-10-01T11:28:44.246379119Z, ./blog/comments -> 2021-10-01T11:28:44.246367784Z, . -> 2021-10-01T11:28:44.246262458Z)
Map(./blog -> 2021-10-01T11:28:46.259498457Z, ./blog/blog1.html -> 2021-10-01T11:28:46.259485377Z)
Map(./blog/blog1.html -> 2021-10-01T11:28:48.264651869Z)
Map(./blog -> 2021-10-01T11:28:50.26752328Z, ./blog/blog2.html -> 2021-10-01T11:28:50.267506107Z)
Map(./blog/comments/GreatPost -> 2021-10-01T11:28:52.272988501Z, ./blog/comments -> 2021-10-01T11:28:52.273004335Z)
Map(./blog/comments -> 2021-10-01T11:28:54.273822303Z)

This suggests that

  1. creating a file changes the mod time stamp of the directory
  2. editing a file, only changes the file's mod time stamp
  3. creating a directory, changes the time stamp of the parent directory
  4. deleting a file changes the time stamp of the parent directory

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment