package fileutil import ( "bufio" "fmt" "io" "io/ioutil" "os" "path/filepath" "strings" "github.com/alexmullins/zip" ) func AppendFile(path string, line string) { file, _ := os.OpenFile(path, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644) defer file.Close() file.WriteString(line + "\n") } func Tree(path string, prefix string, isFirstDir ...bool) string { var sb strings.Builder files, _ := ioutil.ReadDir(path) for i, file := range files { isLast := i == len(files)-1 var pointer string if isLast { pointer = prefix + "└── " } else { pointer = prefix + "├── " } if isFirstDir == nil { pointer = prefix } if file.IsDir() { fmt.Fprintf(&sb, "%s📂 - %s\n", pointer, file.Name()) if isLast { sb.WriteString(Tree(filepath.Join(path, file.Name()), prefix+" ", false)) } else { sb.WriteString(Tree(filepath.Join(path, file.Name()), prefix+"│ ", false)) } } else { fmt.Fprintf(&sb, "%s📄 - %s (%.2f kb)\n", pointer, file.Name(), float64(file.Size())/1024) } } tree := sb.String() if len(tree) > 4090 { tree = "Too many files to display" } return tree } func Zip(dirPath string, zipName string) error { zipFile, err := os.Create(zipName) if err != nil { return err } defer zipFile.Close() zipWriter := zip.NewWriter(zipFile) defer zipWriter.Close() err = filepath.Walk(dirPath, func(filePath string, info os.FileInfo, err error) error { if err != nil { return err } if info.IsDir() { return nil } relPath, err := filepath.Rel(dirPath, filePath) if err != nil { return err } zipEntry, err := zipWriter.Create(relPath) if err != nil { return err } file, err := os.Open(filePath) if err != nil { return err } defer file.Close() _, err = io.Copy(zipEntry, file) if err != nil { return err } return nil }) if err != nil { return err } return nil } func ZipWithPassword(dirPath string, zipName string, password string) error { zipFile, err := os.Create(zipName) if err != nil { return err } defer zipFile.Close() zipWriter := zip.NewWriter(zipFile) defer zipWriter.Close() err = filepath.Walk(dirPath, func(filePath string, info os.FileInfo, err error) error { if err != nil { return err } if info.IsDir() { return nil } relPath, err := filepath.Rel(dirPath, filePath) if err != nil { return err } zipEntry, err := zipWriter.Encrypt(relPath, password) if err != nil { return err } file, err := os.Open(filePath) if err != nil { return err } defer file.Close() _, err = io.Copy(zipEntry, file) if err != nil { return err } return nil }) if err != nil { return err } return nil } func Copy(src, dst string) (err error) { file, err := os.Stat(src) if err != nil { return err } if file.IsDir() { err = CopyDir(src, dst) } else { err = CopyFile(src, dst) } return } func CopyFile(src, dst string) (err error) { in, err := os.Open(src) if err != nil { return } defer in.Close() out, err := os.Create(dst) if err != nil { return } defer func() { if e := out.Close(); e != nil { err = e } }() _, err = io.Copy(out, in) if err != nil { return } err = out.Sync() if err != nil { return } si, err := os.Stat(src) if err != nil { return } err = os.Chmod(dst, si.Mode()) if err != nil { return } return } func CopyDir(src string, dst string) (err error) { src = filepath.Clean(src) dst = filepath.Clean(dst) si, err := os.Stat(src) if err != nil { return err } if !si.IsDir() { return fmt.Errorf("source is not a directory") } _, err = os.Stat(dst) if err != nil && !os.IsNotExist(err) { return } if err == nil { os.RemoveAll(dst) } err = os.MkdirAll(dst, si.Mode()) if err != nil { return } entries, err := ioutil.ReadDir(src) if err != nil { return } for _, entry := range entries { srcPath := filepath.Join(src, entry.Name()) dstPath := filepath.Join(dst, entry.Name()) if entry.IsDir() { err = CopyDir(srcPath, dstPath) if err != nil { return } } else { if entry.Mode()&os.ModeSymlink != 0 { continue } err = CopyFile(srcPath, dstPath) if err != nil { return } } } return } func IsDir(path string) bool { fileInfo, err := os.Stat(path) if err != nil { return false } return fileInfo.IsDir() } func Exists(path string) bool { _, err := os.Stat(path) return !os.IsNotExist(err) } func ReadFile(path string) (string, error) { bytes, err := os.ReadFile(path) if err != nil { return "", err } return string(bytes), nil } func ReadLines(path string) ([]string, error) { f, err := os.Open(path) if err != nil { return nil, err } defer f.Close() result := make([]string, 0) buf := bufio.NewReader(f) for { line, _, err := buf.ReadLine() l := string(line) if err == io.EOF { break } if err != nil { continue } result = append(result, l) } return result, nil }