重要
1. 目录操作
1.1 删除目录
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| // Golang program to illustrate how to
// remove all the files and directories
// from the default directory
package main
import (
"log"
"os"
)
func main() {
// Remove all the directories and files
// Using RemoveAll() function
err := os.RemoveAll("/Users/hex/Documents/go")
if err != nil {
log.Fatal(err)
}
}
|
1.2 创建目录
1
| os.MkdirAll("/tmp/",FileMode)
|
1.3 创建临时目录
方法:
调用io.ioutil
包的 ioutil.TempDir
方法 == == os
包的 os.MkdirTemp
方法
作用:
创建全局唯一的临时目录。但在使用完成后,需要自行删除此目录。
参数:
- 第一个
dir
参数如果不指定,则为os.TempDir()
目录。如Linux下取$TMPDIR
变量,变量空值则为/tmp
目录。
ioutil.TempDir
方法调用过程说明:
- 在目录
/tmp
目录中创建一个名称以prefix
开头的新目录 - 并返回新创建目录的路径
1
2
3
4
5
6
7
| dir, err := ioutil.TempDir("/tmp", "prefix-")
if err != nil {
log.Fatal(err)
}
defer os.RemoveAll(dir)
fmt.Println(dir) // 例如目录名为 "/tmp/prefix-054003078/"
|
1.3.1 创建时间目录
1
2
3
| // logsDir := os.path.Join("/tmp", time.Now().Format("2006/01/02"))
logsDir := filepath.Join("/tmp", time.Now().Format("2006/01/02"))
err := os.MkdirAll(logsDir, 666)
|
1.4 检查路径是否为目录
1
2
3
4
5
6
| func IsDir(name string) bool {
if info, err := os.State(name); err == nil {
return info.IsDir()
}
return false
}
|
1.5 打印当前目录
1.6 文件目录拼接
1
2
|
os.path.join("/tmp", "/text.md")
|
1.7 目录复制
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
| func CopyDir(srcPath, desPath string) error {
//检查目录是否正确
if srcInfo, err := os.Stat(srcPath); err != nil {
return err
} else {
if !srcInfo.IsDir() {
return errors.New("源路径不是一个正确的目录!")
}
}
if desInfo, err := os.Stat(desPath); err != nil {
return err
} else {
if !desInfo.IsDir() {
return errors.New("目标路径不是一个正确的目录!")
}
}
if strings.TrimSpace(srcPath) == strings.TrimSpace(desPath) {
return errors.New("源路径与目标路径不能相同!")
}
err := filepath.Walk(srcPath, func(path string, f os.FileInfo, err error) error {
if f == nil {
return err
}
//复制目录是将源目录中的子目录复制到目标路径中,不包含源目录本身
if path == srcPath {
return nil
}
//生成新路径
destNewPath := strings.Replace(path, srcPath, desPath, -1)
if !f.IsDir() {
CopyFile(path, destNewPath)
} else {
if !FileIsExisted(destNewPath) {
return MakeDir(destNewPath)
}
}
return nil
})
return err
}
|
1.8 遍历目录下所有文件(不包含子目录)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| /* 获取指定路径下的所有文件,只搜索当前路径,不进入下一级目录,可匹配后缀过滤(suffix为空则不过滤)*/
func ListDir(dir, suffix string) (files []string, err error) {
files = []string{}
_dir, err := ioutil.ReadDir(dir)
if err != nil {
return nil, err
}
suffix = strings.ToLower(suffix) //匹配后缀
for _, _file := range _dir {
if _file.IsDir() {
continue //忽略目录
}
if len(suffix) == 0 || strings.HasSuffix(strings.ToLower(_file.Name()), suffix) {
//文件后缀匹配
files = append(files, path.Join(dir, _file.Name()))
}
}
return files, nil
}
|
1.9 遍历目录下所有文件(包含子目录)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| /* 获取指定路径下以及所有子目录下的所有文件,可匹配后缀过滤(suffix为空则不过滤)*/
func WalkDir(dir, suffix string) (files []string, err error) {
files = []string{}
err = filepath.Walk(dir, func(fname string, fi os.FileInfo, err error) error {
if fi.IsDir() {
//忽略目录
return nil
}
if len(suffix) == 0 || strings.HasSuffix(strings.ToLower(fi.Name()), suffix) {
//文件后缀匹配
files = append(files, fname)
}
return nil
})
return files, err
}
|
2. 文件操作
2.1 文件创建或追加内容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
| package main
import (
"fmt"
"io/ioutil"
"log"
"os"
)
func main() {
// ioutil包 创建文件
err := ioutil.WriteFile("temp.txt", []byte("first line\n"), 0644)
if err != nil {
log.Fatal(err)
}
// os包 Create方法 创建文件
f1, _ := os.Create("./temp.txt")
defer f1.close()
// os包 Openfile 读写打开文件
f2, _ := os.Openfile("./temp.txt", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666)
defer f2.close()
// 追加文件内容
file, err := os.OpenFile("temp.txt", os.O_APPEND|os.O_WRONLY, 0644)
defer file.close()
if err != nil {
log.Println(err)
}
if _, err := file.WriteString("second line"); err != nil {
log.Fatal(err)
}
//Print the contents of the file
data, err := ioutil.ReadFile("temp.txt")
if err != nil {
log.Fatal(err)
}
fmt.Println(string(data))
}
|
2.2 创建临时文件
方法:
调用io.ioutil
包的 ioutil.TempFile
方法[Go-旧版] == os
包的 os.CreateTemp
方法[ Go 1.17以上版本]
作用:
创建全局唯一的临时文件。但在使用完成后,需要自行删除此文件。
参数:
ioutil.TempFile
方法调用过程说明:
- 在目录
/tmp
目录中以prefix
开头的名称创建一个新文件 - 打开文件进行读写操作
- 并返回新创建临时文件对象
*os.File
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| // 不指定随机串位置
file, err := ioutil.TempFile("/tmp", "prefix-")
if err != nil {
log.Fatal(err)
}
defer os.Remove(file.Name())
fmt.Println(file.Name()) // 例如文件名为: "/tmp/prefix-054003078"
// 指定随机串位置
file2, err2 := ioutil.TempFile("/tmp", "myname.*.go")
if err2 != nil {
log.Fatal(err2)
}
defer os.Remove(file2.Name())
fmt.Println(file2.Name()) // 例如文件名为: "/tmp/myname.054003078.bat"
|
2.3 检查文件是否存在
1
2
3
4
5
6
7
| func FileIsExisted(filename string) bool {
existed := true
if _, err := os.Stat(filename); os.IsNotExist(err){
existed = false
}
return existed
}
|
2.4 重命名文件
1
| os.Rename("/tmp/1.md", "tmp/2.md")
|
2.5 复制文件
复制文件过程中一定要注意将原始文件的权限也要复制过去,否则可能会导致可执行文件不能执行等问题。
2.5.1 使用io.Copy
方法简单,但是缺少灵活性。如果文件太大,不是一种很好的方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
| func copy(src, dst string) (int64, error) {
// 获取文件权限
sourceFileStat, err := os.Stat(src)
if err != nil {
return 0, err
}
perm := sourceFileStat.Mode()
// 判断文件状态
if !perm.IsRegular() {
return 0, fmt.Errorf("%s is not a regular file", src)
}
// 打开源文件
source, err := os.Open(src)
if err != nil {
return 0, err
}
defer source.Close()
// 创建目标文件
// destination, err := os.Create(dst) //无法复制源文件的所有权限
//复制源文件的所有权限
destination, err := os.OpenFile(des, os.O_RDWR|os.O_CREATE|os.O_TRUNC, perm)
if err != nil {
return 0, err
}
defer destination.Close()
// 拷贝
nBytes, err := io.Copy(destination, source)
return nBytes, err
|
2.5.2 使用ioutil
包WriteFile()
和 ReadFile()
一次性读取输入文件,然后再一次性写入目标文件。依然不是很高效的方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
| func CopyFile(src, des string) (written int64, err error) {
// 打开源文件
srcFile, err := os.Open(src)
if err != nil {
return 0, err
}
defer srcFile.Close()
// 获取源文件的权限
fi, _ := srcFile.Stat()
perm := fi.Mode()
// 打开并读取源文件
input, err := ioutil.ReadFile(src)
if err != nil {
fmt.Println(err)
return 0, err
}
// 创建并写入目标文件
err = ioutil.WriteFile(des, input, perm)
if err != nil {
fmt.Println("Error creating", destinationFile, err)
return 0, err
}
return int64(len(input)), nil
|
2.5.3 使用os
包Read()
和 Write()
- 使用buffer一块块地复制文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
| func CopyFile(src string, des string, bufSize int) (written int64, err error) {
if bufSize <= 0 {
bufSize = 1*1024*1024 // buf大小1M
}
buf := make([]byte, bufSize)
// 打开源文件
srcFile, err := os.Open(src)
if err != nil {
return 0, err
}
defer srcFile.Close()
// 获取文件权限
fileInfo, _ := srcFile.Stat()
perm := fileInfo.Mode()
// 打开目标文件+原权限
destFile, err := os.OpenFile(des, os.O_RDWR|os.O_CREATE|os.O_TRUNC, perm)
if err != nil {
return 0, err
}
defer destFile.Close()
count := 0
for {
n, err := srcFile.Read(buf)
if err != nil && err != io.EOF {
return err
}
if n == 0 {
break
}
if wn, err := destFile.Write(buf[:n]); err != nil {
return err
} else{
count += wn
}
}
return int64(count), nil
}
|
Reference
path/filepath — 兼容操作系统的文件路径操作
Append to an existing file in Go (Golang)