🦖
【Go】Goでファイルのサイズを取得する方法
背景
- Go言語の勉強がてら「ls」コマンドを再現していました.
- そこで、ファイルのサイズを取得する際に少し困ったことがありました.
- それは「io/ioutil」パッケージが非推奨になっていることです
- 「io/ioutil」を使用すれば、ファイルのサイズは容易に取得出来ます
package main
import "fmt"
import "io/ioutil"
func main() {
files, _ := ioutil.ReadDir("./")
for _, f := range files {
fmt.Println(f.Size())
}
}
- なので、今回は「os」パッケージを使用してファイルサイズを取得する方法を紹介します
結論
items, _ := os.ReadDir("./")
for _, item := range items {
// ファイルの情報を取得
file_info, _ := item.Info()
file_size := file_info.Size()
}
解説
ファイルの情報を取得
- osの ReadDir を使用して現在のディレクトリ("./")配下のファイルの情報を取得します
items, err := os.ReadDir("./")
ReadDirは何を返してくれるのか
- ReadDirは []DirEntry 型の値を返却してくれます
dir.go
func ReadDir(name string) ([]DirEntry, error) {
f, err := Open(name)
if err != nil {
return nil, err
}
defer f.Close()
dirs, err := f.ReadDir(-1)
sort.Slice(dirs, func(i, j int) bool { return dirs[i].Name() < dirs[j].Name() })
return dirs, err
}
[]DirEntryについて
- []DirEntry は fs.DirEntry という型で定義されています
dir.go
type DirEntry = fs.DirEntry
- DirEntry を追いかけてみます
fs.go
type DirEntry interface {
// Name returns the name of the file (or subdirectory) described by the entry.
// This name is only the final element of the path (the base name), not the entire path.
// For example, Name would return "hello.go" not "home/gopher/hello.go".
Name() string
// IsDir reports whether the entry describes a directory.
IsDir() bool
// Type returns the type bits for the entry.
// The type bits are a subset of the usual FileMode bits, those returned by the FileMode.Type method.
Type() FileMode
// Info returns the FileInfo for the file or subdirectory described by the entry.
// The returned FileInfo may be from the time of the original directory read
// or from the time of the call to Info. If the file has been removed or renamed
// since the directory read, Info may return an error satisfying errors.Is(err, ErrNotExist).
// If the entry denotes a symbolic link, Info reports the information about the link itself,
// not the link's target.
Info() (FileInfo, error)
}
- Info() に注目します FileInfo を返してくれるそうですね
FileInfoは何を返してくれるのか
- 次は FileInfo を追いかけてみます
- サイズを返してくれそうなところを見つけました !
fs.go
// A FileInfo describes a file and is returned by Stat.
type FileInfo interface {
Name() string // base name of the file
Size() int64 // length in bytes for regular files; system-dependent for others
Mode() FileMode // file mode bits
ModTime() time.Time // modification time
IsDir() bool // abbreviation for Mode().IsDir()
Sys() any // underlying data source (can return nil)
}
どういうことか整理する
- os.ReadDirで取得した値(ファイルひとつひとつ)は Info() を持っている
- Info() は size を持っているということですね
- なので、下記のように取り出してあげれば取得出来そうです
items, _ := os.ReadDir("./")
for _, item := range items {
// ファイルの情報を取得
file_info, _ := item.Info()
file_size := file_info.Size()
}
Discussion