Остання активність 1 month ago

Go 语言文件和文件夹复制 转:https://gist.github.com/r0l1/92462b38df26839a3ca324697c8cba04

copy.go Неформатований
1/* MIT License
2 *
3 * Copyright (c) 2017 Roland Singer [[email protected]]
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in all
13 * copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 */
23
24// CopyFile copies the contents of the file named src to the file named
25// by dst. The file will be created if it does not already exist. If the
26// destination file exists, all it's contents will be replaced by the contents
27// of the source file. The file mode will be copied from the source and
28// the copied data is synced/flushed to stable storage.
29func CopyFile(src, dst string) (err error) {
30 in, err := os.Open(src)
31 if err != nil {
32 return
33 }
34 defer in.Close()
35
36 out, err := os.Create(dst)
37 if err != nil {
38 return
39 }
40 defer func() {
41 if e := out.Close(); e != nil {
42 err = e
43 }
44 }()
45
46 _, err = io.Copy(out, in)
47 if err != nil {
48 return
49 }
50
51 err = out.Sync()
52 if err != nil {
53 return
54 }
55
56 si, err := os.Stat(src)
57 if err != nil {
58 return
59 }
60 err = os.Chmod(dst, si.Mode())
61 if err != nil {
62 return
63 }
64
65 return
66}
67
68// CopyDir recursively copies a directory tree, attempting to preserve permissions.
69// Source directory must exist, destination directory must *not* exist.
70// Symlinks are ignored and skipped.
71func CopyDir(src string, dst string) (err error) {
72 src = filepath.Clean(src)
73 dst = filepath.Clean(dst)
74
75 si, err := os.Stat(src)
76 if err != nil {
77 return err
78 }
79 if !si.IsDir() {
80 return fmt.Errorf("source is not a directory")
81 }
82
83 _, err = os.Stat(dst)
84 if err != nil && !os.IsNotExist(err) {
85 return
86 }
87 if err == nil {
88 return fmt.Errorf("destination already exists")
89 }
90
91 err = os.MkdirAll(dst, si.Mode())
92 if err != nil {
93 return
94 }
95
96 entries, err := ioutil.ReadDir(src)
97 if err != nil {
98 return
99 }
100
101 for _, entry := range entries {
102 srcPath := filepath.Join(src, entry.Name())
103 dstPath := filepath.Join(dst, entry.Name())
104
105 if entry.IsDir() {
106 err = CopyDir(srcPath, dstPath)
107 if err != nil {
108 return
109 }
110 } else {
111 // Skip symlinks.
112 if entry.Mode()&os.ModeSymlink != 0 {
113 continue
114 }
115
116 err = CopyFile(srcPath, dstPath)
117 if err != nil {
118 return
119 }
120 }
121 }
122
123 return
124}
125