画像提供:マイナビニュース

写真拡大

いろいろなフォルダに散らばってるWordファイルを全部まるごと収集したい時ってありませんか。もちろん、OSの検索ツールなどを利用して検索できるのですが、まとめて特定のフォルダにコピーするというのは、なかなか骨の折れる作業です。そこで、今回は、Go言語を利用して、特定ファイルを収集してコピーするツールを作ってみます。

○今回作成するツール - 任意ファイルを検索してコピーするツール

今回作成するのは、特定のパターンに合致するファイルを検索して、任意フォルダにコピーするプログラムです。このツールを作るのに必要なのは、ファイルをコピーする機能と、ファイルを検索する機能です。この二つの機能は、Go言語の標準ライブラリを使って実現できます。

そこで、ツールを作るのに際して、必要となるこの二つの関数の使い方を確認し、その後で、コマンドラインから使えるファイル収集ツールを完成されてみましょう。

○ファイルをコピーする方法

最初にファイルをコピーする方法を確認しておきましょう。意外なことに、原稿執筆時点でGo言語には、ファイルのコピーを行うコマンドは存在しません。そのため、ファイルをコピーしたい時には、次のようにしてファイルの内容を読み込んで、ファイルへ書き込むという手順を自分で記述するしかありません。

以下のプログラムは、「aa.txt」から「bb.txt」へファイルコピーを行うものです。

package main

import (

"io/ioutil"

)

func main() {

infile := "aa.txt"

outfile := "bb.txt"

// ファイルを一度に読み込む --- (*1)

b, err := ioutil.ReadFile(infile)

if err != nil {

panic(err)

}

// ファイルにデータを書き込む ---- (*2)

err = ioutil.WriteFile(outfile, b, 0644)

if err != nil {

panic(err)

}

}

プログラムを実行するには、上記プログラムを「copyfile.go」という名前で保存します。そして、コマンドラインから「go run copyfile.go」と入力すると、プログラムを実行できます。

上記のプログラムでは、(*1)の部分でファイルの内容全部をメモリに読み込みます。そして、(*2)の部分でファイルへ書き出します。ioutilのReadFileとWriteFileを利用することで、手軽にファイルの読み書きが可能です。ただし、このプログラムは、最も単純なファイルコピーの実装方法であり、巨大なサイズのファイルをコピーすることはできません。ファイルのコピーは、様々な手法が考えられるので、興味のある方は調べて見ると良いでしょう。

また、Go言語の特徴ですが、多くの関数では処理の実行が失敗した場合、error型のデータが返されます。そのため、ReadFileやWriteFileで処理が失敗したかどうかを確認するには、戻り値がnilかどうかを確認します。もし、nilであれば正しく実行できたことになり、nilでなければerror型のデータを確認し処理が失敗した理由を確かめることになります。

○ファイルの一覧を取得する方法

次に、ファイルの一覧を取得する方法を見てみましょう。最初にカレントディレクトリにあるファイル一覧を取得してみます。

package main

import (

"fmt"

"log"

"io/ioutil"

)

func main() {

// カレントディレクトリのファイル一覧を得る

files, err := ioutil.ReadDir(".")

if err != nil {

log.Fatal(err)

}

// 取得した一覧を表示

for _, file := range files {

fmt.Println(file.Name())

}

}

上記のプログラムを「files.go」という名前で保存します。そして、コマンドラインから「go run files.go」を実行してみましょう。すると、カレントディレクトリにあるファイルの一覧を取得して表示します。

指定ディレクトリにあるファイル一覧を取得するのが、ioutil.ReadDir関数です。引数にディレクトリを与えると、string型のスライスを返します。ちなみに、ファイルの一覧に関しては、前回詳しく解説しています。

○特定のファイルをまるごと収集するツール

ここまでの部分で、Goの関数の使い方を確認できました。それでは、特定のファイルをまるごと収集するツールを作ってみましょう。以下のプログラムを「atumeru.go」という名前で保存しましょう。

package main

import (

"os"

"fmt"

"log"

"io/ioutil"

"path/filepath"

"regexp"

)

var pattern *regexp.Regexp // 検索パターン

var files = []string{} // 収集したファイル

func main() {

// コマンドライン引数を得る --- (*1)

if (len(os.Args)