こんにちわ
現在、ファイルやディレクトリを簡単に操作できるTUIを作っていて、
ファイルやディレクトリの情報を取得して表示する必要があり、調べたら意外と面倒だったので、
忘れないうちに備忘録として残ります。
ディレクトリ内のファイル・ディレクトリを取得
Goではfilepath.WalkFunc
でディレクトリ内のファイル・ディレクトリを再帰的に取得してくれますが、
今回はカレントディレクトリの情報を取得できればいいので、ioutil.ReadDir
を使用します。
ReadDir
を使用すると、[]os.FileInfo
構造体を取得できます。
type FileInfo interface {
Name() string // ファイル名
Size() int64 // ファイルサイズ
Mode() FileMode // パーミッション
ModTime() time.Time // 更新日
IsDir() bool // ディレクトリの場合はtrue
Sys() interface{} // syscall.Stat_tに型アサーションすると更に詳細情報を取得可能
}
とこんな感じでデータを取得できます。
パーミッション
FileInfo.Mode().String()
でおなじみのフォーマットに変換してくれます。
OwnerとGroup
ファイルの所有者と所有者が所属しているグループを取得したい場合は、
FilInfo.Sys()
をsysacll.Stat_t
に型アサーションする必要があります。
if stat, ok := file.Sys().(*syscall.Stat_t); ok {
// syscall.Stat_t.UidがユーザIDになります
uid := strconv.Itoa(int(stat.Uid))
// os/userパッケージのLookupIdにUidを渡すとユーザ名を取得できます
u, err := user.LookupId(uid)
if err != nil {
owner = uid
} else {
owner = u.Username
}
// syscall.Stat_t.GidがグループIDになります
gid := strconv.Itoa(int(stat.Gid))
// os/userパッケージのLookupGroupIdにGidを渡すとグループ名を取得できます
g, err := user.LookupGroupId(gid)
if err != nil {
group = gid
} else {
group = g.Name
}
}
日時
作成日や更新日などを取得したい場合、OSごとに取得方法が異なります。
syscall.Stat_t
に更新日などのフィールドがありますが、OSごとにフィールドが異なります。
Macの場合はこうなっています。
Linuxの場合、Birthtimespec
に相当するフィールドはない様です。
type Stat_t struct {
// 日時の部分だけ抽出
Atimespec Timespec
Mtimespec Timespec
Ctimespec Timespec
Birthtimespec Timespec
}
自前で実装は結構大変なので、ここは先人の知恵を借ります。
こちらのライブラリを使用すると、差分吸収してくれます。
OSによっては取得できないデータもあるのでご注意を。
まとめ
ファイル情報を取得するだけなのに何かと面倒ですね。
ls
コマンド凄すぎない?と思いました。
あと、先人の知恵はすごいので、どんどん使っていきましょう。