やりたいこと
処理が終わった一時ディレクトリ内を綺麗したい。
でも、親ディレクトリは残しておきたい。
ディレクトリ内は階層が統一されていない。
削除したいディレクトリ構造
.
├── parentDir1
│ ├── ChildDirA
│ │ └── ChildDirAA
│ └── ChildDirB
└── parentDir2
試したこと
2つの方法で実施
- ReadDir
- filepath.WalkDir
filepath.WalkDirのほうが処理速度が早いという記事情報あり。
ReadDirでディレクトリ内を取得
package main
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
)
func main() {
dir := "your_directory_path" // 対象のディレクトリパスをここに指定
err := removeSubdirectories(dir)
if err != nil {
fmt.Printf("Error: %v\n", err)
} else {
fmt.Println("All subdirectories removed successfully.")
}
}
func removeSubdirectories(dir string) error {
// ディレクトリ内の全てのファイルとサブディレクトリを取得
files, err := ioutil.ReadDir(dir)
if err != nil {
return err
}
for _, file := range files {
if file.IsDir() {
// サブディレクトリのフルパスを取得
subDirPath := filepath.Join(dir, file.Name())
fmt.Printf("Removing directory: %s\n", subDirPath)
// サブディレクトリを削除
err = os.RemoveAll(subDirPath)
if err != nil {
return err
}
}
}
return nil
}
結果
Removing directory: /parentDir1/ChildDirA
Removing directory: /parentDir1/ChildDirB
All subdirectories removed successfully.
正常に終了。
filepath.WalkDirで取得
package main
import (
"fmt"
"os"
"path/filepath"
)
func main() {
dir := "your_directory_path" // 対象のディレクトリパスをここに指定
err := removeSubdirectoriesUsingWalkDir(dir)
if err != nil {
fmt.Printf("Error: %v\n", err)
} else {
fmt.Println("All subdirectories removed successfully.")
}
}
func removeSubdirectoriesUsingWalkDir(root string) error {
return filepath.WalkDir(root, func(path string, d os.DirEntry, err error) error {
if err != nil {
return err
}
// ルートディレクトリそのものは削除しない
if path == root {
return nil
}
// ディレクトリであれば削除
if d.IsDir() {
fmt.Printf("Removing directory: %s\n", path)
return os.RemoveAll(path)
}
return nil
})
}
結果
Removing directory: /parentDir1/ChildDirA
Error: open /parentDir1/ChildDirA: no such file or directory
エラー
/parentDir1/ChildDirAディレクトリがないというエラーが出力されています。
/parentDir1/ChildDirAは削除されていますが、
/parentDir1/ChildDirBは削除されていません。
削除部分を以下に変更してみる
削除を実行しないで、nilを返す
// ディレクトリであれば削除
if d.IsDir() {
fmt.Printf("Removing directory: %s\n", path)
//return os.RemoveAll(path)
return nil
}
結果
Removing directory: /parentDir1/ChildDirA
Removing directory: /parentDir1ChildDirA/ChildDirAA
Removing directory: /parentDir1/ChildDirB
All subdirectories removed successfully.
どうやら、ChildDirAを削除した後に子ディレクトリを削除しようとしてエラーになっている。
削除の前にディレクトリの存在確認を追加してみる。
func removeSubdirectoriesUsingWalkDir(root string) error {
return filepath.WalkDir(root, func(path string, d os.DirEntry, err error) error {
if err != nil {
// ディレクトリの存在確認
if _, err := os.Stat(path); os.IsNotExist(err) {
fmt.Printf("Directory does not exist: %s\n", path)
return nil
}
return err
}
// ルートディレクトリそのものは削除しない
if path == root {
return nil
}
// ディレクトリであれば削除
if d.IsDir() {
fmt.Printf("Removing directory: %s\n", path)
return os.RemoveAll(path)
}
return nil
})
}
結果
Removing directory: /parentDir1/ChildDirA
Directory does not exist: /parentDir1/ChildDirA
Removing directory: /parentDir1/ChildDirB
Directory does not exist: /parentDir1/ChildDirB
All subdirectories removed successfully.
ディレクトリ内の削除は完了
なぜか/parentDir1/ChildDirAと/parentDir1/ChildDirBのそれぞれで存在確認エラー
子ディレクトリを削除するが、その後に子ディレクトリ内の探索が行われる
その為、エラーとなる。
解決方法
filepath.WalkDirでディレクトリ内の探索時、エラーの判定後にエラーの種別が存在確認エラーの場合は無視する