以下の内容はhttps://devlights.hatenablog.com/entry/2025/09/30/073000より取得しました。


Goメモ-622 (Windowsでファイルの作成時間を変更する)(syscall, Creation Time, os.Chtimesでは無理)

関連記事

GitHub - devlights/blog-summary: ブログ「いろいろ備忘録日記」のまとめ

概要

以下、自分用のメモです。

大した内容では無いのですが、Windows上のファイルの作成時刻(Creation Time) を変更したい場合、os.Chtimesでは変更できません。そもそも、Linuxではctimeは変更不可なので、統一性という意味でこうなっていると思っています。

(WindowsとLinuxでは atime,mtime,ctime の意味が異なる)

かといって、場合によっては変更したいときもあったりします。その場合は、syscall.SetFileTimeを利用すれば変更できます。この関数は Windows 版のsyscallパッケージにのみ存在します。

サンプル

main.go

//go:build windows

package main

import (
    "log"
    "syscall"
    "time"
)

func main() {
    //
    // WindowsとLinuxでは atime,mtime,ctime の意味が異なる。
    //
    // Linux:
    //   - atime (Access Time)       - アクセス時間:ファイルが最後に読み取られた時刻
    //   - mtime (Modification Time) - 更新時間:ファイルの内容が最後に変更された時刻
    //   - ctime (Change Time)       - 変更時間:ファイルのメタデータ(権限、所有者、リンク数など)が最後に変更された時刻
    //
    // Windows:
    //   - atime (Access Time)   - アクセス時間 (Last Access Time)
    //   - mtime (Write Time)    - 更新時間 (Last Write Time)
    //   - ctime (Creation Time) - 作成時間 (Creation Time)
    //
    // Windowsの ctime (Creation Time) は変更可能であるが、Linuxの ctime (Change Time) は変更不可。
    // Windowsの場合に 3つの時間 (atime,mtime,ctime) を変更したい場合は syscall.SetFileTime() を用いる。
    //
    // osパッケージに存在する os.Chtime() では、WindowsのCreation Timeは変更できない。
    //
    //   func Chtimes(name string, atime time.Time, mtime time.Time) error
    //
    // syscallには SetFileTime 関数が存在する。
    //
    //   func SetFileTime(handle Handle, ctime *Filetime, atime *Filetime, wtime *Filetime) (err error)
    //
    // 第一引数の Handle も syscall の関数を用いて取得する.
    //
    log.SetFlags(0)
    if err := run(); err != nil {
        log.Fatal(err)
    }
}

func run() error {
    const (
        FilePath = "./test.txt"
    )
    var (
        fname *uint16
        err   error
    )
    fname, err = syscall.UTF16PtrFromString(FilePath)
    if err != nil {
        return err
    }

    var (
        handle       syscall.Handle
        access       uint32 = syscall.FILE_WRITE_ATTRIBUTES
        mode         uint32 = syscall.FILE_SHARE_READ | syscall.FILE_SHARE_WRITE | syscall.FILE_SHARE_DELETE
        createMode   uint32 = syscall.OPEN_EXISTING
        attrs        uint32 = syscall.FILE_ATTRIBUTE_NORMAL
        templateFile int32  = 0
    )
    handle, err = syscall.CreateFile(fname, access, mode, nil, createMode, attrs, templateFile)
    if err != nil {
        return err
    }
    defer syscall.CloseHandle(handle)

    var (
        jst, _ = time.LoadLocation("Asia/Tokyo")
        a      = time.Date(2025, 1, 1, 0, 0, 0, 0, jst).UnixNano()
        m      = time.Date(2025, 1, 2, 0, 0, 0, 0, jst).UnixNano()
        c      = time.Date(2025, 1, 3, 0, 0, 0, 0, jst).UnixNano()
        atime  = syscall.NsecToFiletime(a)
        mtime  = syscall.NsecToFiletime(m)
        ctime  = syscall.NsecToFiletime(c)
    )
    err = syscall.SetFileTime(handle, &ctime, &atime, &mtime)
    if err != nil {
        return err
    }

    return nil
}

Taskfile.yml

# https://taskfile.dev

version: '3'

vars:
  select_object: Select-Object LastAccessTime,LastWriteTime,CreationTime | Format-List
  new_item_cmd: New-Item test.txt -ItemType File -Force | {{.select_object}}
  rm_item_cmd: Remove-Item test.txt -Force
  get_item_cmd: Get-Item test.txt | {{.select_object}}

tasks:
  default:
    cmds:
      - powershell "{{.new_item_cmd}}"
      - defer: powershell "{{.rm_item_cmd}}"
      - go run .
      - powershell "{{.get_item_cmd}}"

実行結果

$ task
task: [default] powershell "New-Item test.txt -ItemType File -Force | Select-Object LastAccessTime,LastWriteTime,CreationTime | Format-List"
                                                                                                                                                                               

LastAccessTime : 2025/09/16 23:17:00
LastWriteTime  : 2025/09/16 23:17:00
CreationTime   : 2025/09/16 23:17:00



task: [default] go run .
task: [default] powershell "Get-Item test.txt | Select-Object LastAccessTime,LastWriteTime,CreationTime | Format-List"                                                         
                                                                                                                                                                               

LastAccessTime : 2025/01/01 0:00:00
LastWriteTime  : 2025/01/02 0:00:00
CreationTime   : 2025/01/03 0:00:00



task: [default] powershell "Remove-Item test.txt -Force"

参考情報

Goのおすすめ書籍


過去の記事については、以下のページからご参照下さい。

サンプルコードは、以下の場所で公開しています。




以上の内容はhttps://devlights.hatenablog.com/entry/2025/09/30/073000より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14