Files
argus-go/rear/pkg/utils/file_utils.go
T

498 lines
11 KiB
Go

package utils
import (
"bufio"
"crypto/md5"
"crypto/sha256"
"fmt"
"io"
"os"
"path/filepath"
"strings"
"time"
)
// FileInfo 文件信息结构体
type FileInfo struct {
Name string `json:"name"`
Path string `json:"path"`
Size int64 `json:"size"`
ModTime time.Time `json:"mod_time"`
IsDir bool `json:"is_dir"`
Ext string `json:"ext"`
}
// 1. 检查文件或目录是否存在
func Exists(path string) bool {
_, err := os.Stat(path)
return !os.IsNotExist(err)
}
// 2. 检查是否为目录
func IsDir(path string) bool {
info, err := os.Stat(path)
if err != nil {
return false
}
return info.IsDir()
}
// 3. 检查是否为文件
func IsFile(path string) bool {
info, err := os.Stat(path)
if err != nil {
return false
}
return !info.IsDir()
}
// 4. 获取指定目录下的所有文件夹
func GetDirectories(dirPath string) ([]string, error) {
var dirs []string
entries, err := os.ReadDir(dirPath)
if err != nil {
return nil, fmt.Errorf("读取目录失败: %w", err)
}
for _, entry := range entries {
if entry.IsDir() {
dirs = append(dirs, entry.Name())
}
}
return dirs, nil
}
// 5. 获取指定目录下指定格式的文件
func GetFilesByExtension(dirPath string, extensions ...string) ([]string, error) {
var files []string
// 标准化扩展名(确保以.开头)
for i, ext := range extensions {
if !strings.HasPrefix(ext, ".") {
extensions[i] = "." + ext
}
extensions[i] = strings.ToLower(extensions[i])
}
entries, err := os.ReadDir(dirPath)
if err != nil {
return nil, fmt.Errorf("读取目录失败: %w", err)
}
for _, entry := range entries {
if !entry.IsDir() {
fileExt := strings.ToLower(filepath.Ext(entry.Name()))
for _, ext := range extensions {
if fileExt == ext {
files = append(files, entry.Name())
break
}
}
}
}
return files, nil
}
// 6. 找到指定目录下第一个符合格式的文件
func GetFirstFileByExtension(dirPath string, extensions ...string) (string, error) {
files, err := GetFilesByExtension(dirPath, extensions...)
if err != nil {
return "", err
}
if len(files) == 0 {
return "", fmt.Errorf("未找到符合扩展名的文件")
}
return files[0], nil
}
// 7. 递归获取目录下所有文件
func GetAllFiles(dirPath string, recursive bool) ([]FileInfo, error) {
var files []FileInfo
if recursive {
err := filepath.Walk(dirPath, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if !info.IsDir() {
files = append(files, FileInfo{
Name: info.Name(),
Path: path,
Size: info.Size(),
ModTime: info.ModTime(),
IsDir: false,
Ext: filepath.Ext(info.Name()),
})
}
return nil
})
return files, err
} else {
entries, err := os.ReadDir(dirPath)
if err != nil {
return nil, fmt.Errorf("读取目录失败: %w", err)
}
for _, entry := range entries {
if !entry.IsDir() {
info, err := entry.Info()
if err != nil {
continue
}
files = append(files, FileInfo{
Name: info.Name(),
Path: filepath.Join(dirPath, info.Name()),
Size: info.Size(),
ModTime: info.ModTime(),
IsDir: false,
Ext: filepath.Ext(info.Name()),
})
}
}
return files, nil
}
}
// 递归获取目录下所有文件夹
func GetAllDirs(dirPath string, recursive bool) ([]FileInfo, error) {
var dirs []FileInfo
if recursive {
err := filepath.Walk(dirPath, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
// 只收集目录,排除根目录本身
if info.IsDir() && path != dirPath {
dirs = append(dirs, FileInfo{
Name: info.Name(),
Path: path,
Size: 0, // 目录大小通常为0或不适用
ModTime: info.ModTime(),
IsDir: true,
Ext: "", // 目录没有扩展名
})
}
return nil
})
return dirs, err
} else {
entries, err := os.ReadDir(dirPath)
if err != nil {
return nil, fmt.Errorf("读取目录失败: %w", err)
}
for _, entry := range entries {
if entry.IsDir() {
info, err := entry.Info()
if err != nil {
continue
}
dirs = append(dirs, FileInfo{
Name: info.Name(),
Path: filepath.Join(dirPath, info.Name()),
Size: 0, // 目录大小通常为0或不适用
ModTime: info.ModTime(),
IsDir: true,
Ext: "", // 目录没有扩展名
})
}
}
return dirs, nil
}
}
// 8. 删除文件或目录
func Delete(path string) error {
if !Exists(path) {
return fmt.Errorf("路径不存在: %s", path)
}
return os.RemoveAll(path)
}
// 9. 创建目录(递归创建)
func CreateDir(dirPath string) error {
return os.MkdirAll(dirPath, 0755)
}
// 10. 复制文件
func CopyFile(src, dst string) error {
sourceFile, err := os.Open(src)
if err != nil {
return fmt.Errorf("打开源文件失败: %w", err)
}
defer sourceFile.Close()
// 确保目标目录存在
dstDir := filepath.Dir(dst)
if err := CreateDir(dstDir); err != nil {
return fmt.Errorf("创建目标目录失败: %w", err)
}
destFile, err := os.Create(dst)
if err != nil {
return fmt.Errorf("创建目标文件失败: %w", err)
}
defer destFile.Close()
_, err = io.Copy(destFile, sourceFile)
if err != nil {
return fmt.Errorf("复制文件失败: %w", err)
}
return nil
}
// 11. 移动/重命名文件
func MoveFile(src, dst string) error {
// 确保目标目录存在
dstDir := filepath.Dir(dst)
if err := CreateDir(dstDir); err != nil {
return fmt.Errorf("创建目标目录失败: %w", err)
}
return os.Rename(src, dst)
}
// 12. 读取文件全部内容
func ReadFile(filePath string) (string, error) {
content, err := os.ReadFile(filePath)
if err != nil {
return "", fmt.Errorf("读取文件失败: %w", err)
}
return string(content), nil
}
// 13. 按行读取文件
func ReadFileLines(filePath string) ([]string, error) {
file, err := os.Open(filePath)
if err != nil {
return nil, fmt.Errorf("打开文件失败: %w", err)
}
defer file.Close()
var lines []string
scanner := bufio.NewScanner(file)
for scanner.Scan() {
lines = append(lines, scanner.Text())
}
if err := scanner.Err(); err != nil {
return nil, fmt.Errorf("读取文件失败: %w", err)
}
return lines, nil
}
// 14. 写入文件内容
func WriteFile(filePath, content string) error {
// 确保目录存在
dir := filepath.Dir(filePath)
if err := CreateDir(dir); err != nil {
return fmt.Errorf("创建目录失败: %w", err)
}
return os.WriteFile(filePath, []byte(content), 0644)
}
// 15. 追加写入文件
func AppendFile(filePath, content string) error {
// 确保目录存在
dir := filepath.Dir(filePath)
if err := CreateDir(dir); err != nil {
return fmt.Errorf("创建目录失败: %w", err)
}
file, err := os.OpenFile(filePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
return fmt.Errorf("打开文件失败: %w", err)
}
defer file.Close()
_, err = file.WriteString(content)
return err
}
// 16. 获取文件大小
func GetFileSize(filePath string) (int64, error) {
info, err := os.Stat(filePath)
if err != nil {
return 0, fmt.Errorf("获取文件信息失败: %w", err)
}
return info.Size(), nil
}
// 17. 获取文件修改时间
func GetModTime(filePath string) (time.Time, error) {
info, err := os.Stat(filePath)
if err != nil {
return time.Time{}, fmt.Errorf("获取文件信息失败: %w", err)
}
return info.ModTime(), nil
}
// 18. 获取文件扩展名
func GetExtension(filePath string) string {
return filepath.Ext(filePath)
}
// 19. 获取文件名(不含扩展名)
func GetFileName(filePath string) string {
base := filepath.Base(filePath)
ext := filepath.Ext(base)
return strings.TrimSuffix(base, ext)
}
// 20. 获取文件基本名称(含扩展名)
func GetBaseName(filePath string) string {
return filepath.Base(filePath)
}
// 21. 获取文件目录
func GetDir(filePath string) string {
return filepath.Dir(filePath)
}
// 22. 计算文件MD5哈希值
func GetFileMD5(filePath string) (string, error) {
file, err := os.Open(filePath)
if err != nil {
return "", fmt.Errorf("打开文件失败: %w", err)
}
defer file.Close()
hash := md5.New()
if _, err := io.Copy(hash, file); err != nil {
return "", fmt.Errorf("计算哈希失败: %w", err)
}
return fmt.Sprintf("%x", hash.Sum(nil)), nil
}
// 23. 计算文件SHA256哈希值
func GetFileSHA256(filePath string) (string, error) {
file, err := os.Open(filePath)
if err != nil {
return "", fmt.Errorf("打开文件失败: %w", err)
}
defer file.Close()
hash := sha256.New()
if _, err := io.Copy(hash, file); err != nil {
return "", fmt.Errorf("计算哈希失败: %w", err)
}
return fmt.Sprintf("%x", hash.Sum(nil)), nil
}
// 24. 清空目录内容(保留目录本身)
func CleanDir(dirPath string) error {
entries, err := os.ReadDir(dirPath)
if err != nil {
return fmt.Errorf("读取目录失败: %w", err)
}
for _, entry := range entries {
path := filepath.Join(dirPath, entry.Name())
if err := os.RemoveAll(path); err != nil {
return fmt.Errorf("删除 %s 失败: %w", path, err)
}
}
return nil
}
// 25. 获取目录大小
func GetDirSize(dirPath string) (int64, error) {
var size int64
err := filepath.Walk(dirPath, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if !info.IsDir() {
size += info.Size()
}
return nil
})
return size, err
}
// 26. 格式化文件大小
func FormatFileSize(bytes int64) string {
const unit = 1024
if bytes < unit {
return fmt.Sprintf("%d B", bytes)
}
div, exp := int64(unit), 0
for n := bytes / unit; n >= unit; n /= unit {
div *= unit
exp++
}
return fmt.Sprintf("%.1f %cB", float64(bytes)/float64(div), "KMGTPE"[exp])
}
// 27. 搜索文件(按文件名模式)
func SearchFiles(dirPath, pattern string, recursive bool) ([]string, error) {
var matches []string
if recursive {
err := filepath.Walk(dirPath, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if !info.IsDir() {
matched, err := filepath.Match(pattern, info.Name())
if err != nil {
return err
}
if matched {
matches = append(matches, path)
}
}
return nil
})
return matches, err
} else {
entries, err := os.ReadDir(dirPath)
if err != nil {
return nil, fmt.Errorf("读取目录失败: %w", err)
}
for _, entry := range entries {
if !entry.IsDir() {
matched, err := filepath.Match(pattern, entry.Name())
if err != nil {
return nil, err
}
if matched {
matches = append(matches, filepath.Join(dirPath, entry.Name()))
}
}
}
return matches, nil
}
}
// 28. 获取当前工作目录
func GetCurrentDir() (string, error) {
return os.Getwd()
}
// 29. 改变工作目录
func ChangeDir(dirPath string) error {
return os.Chdir(dirPath)
}