Go言語_ホワイトリスト方式のファイル削除
ファイル削除
ホワイトリストファイルに記載したものは削除しない、という方式の削除プログラムです。
ホワイトリスト
ホワイトリストは下記の形式になります。
アスタリスクをつけると、その子要素は削除しないという指定になります。
node_modules/jquery/dist/*
node_modules/jquery/LICENSE.txt
プログラム
package main
import (
"bufio"
"errors"
"flag"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"regexp"
"strings"
)
/*!
* @brief ホワイトリストに含まれるか判定する
* @param[in] filePath 操作対象のファイルパス
* @param[in] whiteList ホワイトリスト情報
* @return true or false
*/
func isWhiteFile(filePath string, whiteFile string) bool {
// 完全一致の判定
if filePath == whiteFile {
return true
}
// 親階層の判定
if strings.HasPrefix(whiteFile, filePath) {
return true
}
// アスタリスク指定は正規表現で判定する
if strings.Contains(whiteFile, "*") {
reg := regexp.MustCompile(whiteFile)
return reg.MatchString(filePath)
}
return false
}
/*!
* @brief 削除してよいか判定する
* @param[in] filePath 操作対象のファイルパス
* @param[in] whiteList ホワイトリスト情報
* @return true or false
*/
func isNeedDelete(filePath string, whiteList []string) bool {
for _, whiteFile := range whiteList {
if isWhiteFile(filePath, whiteFile) {
return false
}
}
return true
}
/*!
* @brief ファイルを削除する
* @param[in] filePath 変更対象のディレクトリ名
* @param[in] whiteList ホワイトリスト情報
* @return error エラー情報
*/
func deleteFile(filePath string, whiteList []string) error {
// 削除対象であるか判定する
if !isNeedDelete(filePath, whiteList) {
return nil
}
// ファイルを削除する
if err := os.Remove(filePath); err != nil {
return err
}
return nil
}
/*!
* @brief ディレクトリ名を再帰的に変更する
* @param[in] rootDir トップディレクトリ名
* @param[in] whiteList ホワイトリスト情報
* @return error エラー情報
*/
func deleteFileRecursive(rootDir string, whiteList []string) error {
files, err := ioutil.ReadDir(rootDir)
if err != nil {
return err
}
for _, file := range files {
fullPath := filepath.Join(rootDir, file.Name())
// ディレクトリならば再帰する
if file.IsDir() {
err = deleteFileRecursive(fullPath, whiteList)
if err != nil {
return err
}
}
err = deleteFile(fullPath, whiteList)
if err != nil {
return err
}
}
return nil
}
/*!
* @brief オプション解析を行う。
* @retval string ターゲットとなるディレクトリ名
* @retval string ホワイトリスト用ファイルパス
* @retval error エラー情報
*/
func analyzeOption() (string, string, error) {
flag.Usage = func() {
fmt.Fprintf(os.Stderr, "Usage: %s [OPTION] DIR:\n",
filepath.Base(os.Args[0]))
flag.PrintDefaults()
}
optF := flag.String("f", "", "white list filepath")
flag.Parse()
if flag.NArg() != 1 {
flag.Usage()
return "", "", errors.New("Error: Invalid arguments.")
}
return (flag.Args())[0], *optF, nil
}
/*!
* @brief ホワイトリストを読み込みスライスに格納する。
* @param[in] filename ファイルパス
* @retval []string ファイル内容
* @retval error エラー情報
*/
func readWhiteList(filename string) ([]string, error) {
// ファイルを開く
fd, err := os.Open(filename)
if err != nil {
return nil, err
}
defer fd.Close() // return時に閉じる
// Scannerで読み込む
lines := make([]string, 0, 128)
scanner := bufio.NewScanner(fd)
for scanner.Scan() {
lines = append(lines, scanner.Text())
}
if serr := scanner.Err(); serr != nil {
return nil, serr
}
return lines, nil
}
/*!
* @brief 初期化処理
* @retval string ディレクトリ名
* @retval string ファイル名
* @retval error エラー情報
*/
func initialize() (string, []string, error) {
// オプション解析
target, filename, err := analyzeOption()
if err != nil {
return "", nil, err
}
// ホワイトリストが指定されていれば読み込む
var whiteList []string
if filename != "" {
whiteList, err = readWhiteList(filename)
if err != nil {
return "", nil, err
}
}
return target, whiteList, nil
}
/*!
* @brief main routine
* @return 成功時には0を返し、失敗時には1を返す。
*/
func main() {
target, whiteList, err := initialize()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
err = deleteFileRecursive(target, whiteList)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
os.Exit(0)
}
実行
npmインストールしたモジュールの内、不要なものを削除する場合に用います。
go run deleter.go -f whitelist.conf node_modules/