Goでcpみたいなものを作ってみました
この記事は初心者🌱の自分のためのメモに近いです。ご容赦を。
paizaで学習するときに、いちいちディレクトリを複製するのが手間だったのでディレクトリの複製がしたかった。
ちょうどGoでなんでもいいからツールを作ってみたかったから作った。
cpなんていう便利なものがあったことは知らなかった
主に使用したパッケージ
どれも標準パッケージですね
ioospath/filepath
今回のリポジトリ
面白かったところ
os.Argsについて
これを使用することによって、go run 以降の引数を取得できる。
go run . filenameだと os.Argsの要素の0番目が.なのでファイルのパス。1番目がfilenameとなる。
os.Argsの要素の1番目がある場合のみプログラムを続けたかったので、以下のように書いた。
if len(os.Args) == 2 {
directory_name = os.Args[1]
} else {
os.Exit(1)
}
osパッケージまわりについて
os.Statは返り値にfs.FileInfoとerrorを持つ。
fs.FileInfoとはなんぞや。
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)
}
ということらしい。
ぱっと見で理解できそうなのは、NameとSizeくらいかな...
と思ってたらIsDirが目についた。
これ、ディレクトリかそうじゃないかboolで返してくれるじゃん。天才じゃん。
ってことで利用する。
osパッケージにはディレクトリ作成の関数と、ファイル作成の関数が別で用意されているので、IsDirを使って区別できた。
filepath.Walk()について
func Walk(root string, fn WalkFunc) error
rootには探索したいディレクトリを入れる。
fnのWalkFuncってなに。
type WalkFunc func(path string, info fs.FileInfo, err error) error
ってことらしい。
おそらく、 filepath.Walk()君が、WalkFunc君の引数にそれぞれのディレクトリ等のパスとかinfoを投げて、それらを利用した関数を書けるということだと思う。
実際に書いてみた。
func make_directory_or_file(filename string) {
var new_path string
filepath.Walk("original_directory", func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
new_path = strings.Replace(path, "original_directory", filename, -1)
if info.IsDir() {
err := os.MkdirAll(new_path, 0755)
if err != nil {
log.Println(err)
os.Exit(1)
}
} else {
dst, err := os.Create(new_path)
if err != nil {
log.Println(err)
os.Exit(1)
}
src, err := os.Open(path)
if err != nil {
log.Println(err)
os.Exit(1)
}
_, err = io.Copy(dst, src)
if err != nil {
log.Println(err)
os.Exit(1)
}
}
return nil
})
}
これはさっきのosパッケージも使って書いてみた。
わりかしコンパクトに書けたのではないかと思いたい。
ひとりごと
Walkで思い出したけど、これはおそらくグラフ理論の木構造とか使ってんのかなぁみたいな。
静的解析ツールを学習する機会があったけどおそらく今回のWalkと似たことをやっていたんだと思う。抽象構文木をつかって、要素を一つ一つに関数を実行してたんだね。今やっと理解できた。ってことで多少は理解が進んだから静的解析ツールの話も記事にまとめます。
今回の学習を先にしていればもっと理解が早かったのかあ…
感想
cpコマンドとほとんど同じことをやってるので便利なツールができた!みたいな感じにはならなかったけど得たものが凄い多かった。
こういう感じで簡単なものでもツールいっぱい作ってみようと思う。