github.com/webx-top/com@v1.2.12/dir.go (about) 1 // Copyright 2013 com authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"): you may 4 // not use this file except in compliance with the License. You may obtain 5 // a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 // License for the specific language governing permissions and limitations 13 // under the License. 14 15 package com 16 17 import ( 18 "errors" 19 "os" 20 "path/filepath" 21 "strings" 22 ) 23 24 // IsDir returns true if given path is a directory, 25 // or returns false when it's a file or does not exist. 26 func IsDir(dir string) bool { 27 f, e := os.Stat(dir) 28 if e != nil { 29 return false 30 } 31 return f.IsDir() 32 } 33 34 func statDir(dirPath, recPath string, includeDir, isDirOnly bool) ([]string, error) { 35 dir, err := os.Open(dirPath) 36 if err != nil { 37 return nil, err 38 } 39 defer dir.Close() 40 41 fis, err := dir.Readdir(0) 42 if err != nil { 43 return nil, err 44 } 45 46 var statList []string 47 for _, fi := range fis { 48 if strings.Contains(fi.Name(), ".DS_Store") { 49 continue 50 } 51 52 relPath := filepath.Join(recPath, fi.Name()) 53 curPath := filepath.Join(dirPath, fi.Name()) 54 if fi.IsDir() { 55 if includeDir { 56 statList = append(statList, relPath+"/") 57 } 58 s, err := statDir(curPath, relPath, includeDir, isDirOnly) 59 if err != nil { 60 return nil, err 61 } 62 statList = append(statList, s...) 63 } else if !isDirOnly { 64 statList = append(statList, relPath) 65 } 66 } 67 return statList, nil 68 } 69 70 // StatDir gathers information of given directory by depth-first. 71 // It returns slice of file list and includes subdirectories if enabled; 72 // it returns error and nil slice when error occurs in underlying functions, 73 // or given path is not a directory or does not exist. 74 // 75 // Slice does not include given path itself. 76 // If subdirectories is enabled, they will have suffix '/'. 77 func StatDir(rootPath string, includeDir ...bool) ([]string, error) { 78 if !IsDir(rootPath) { 79 return nil, errors.New("not a directory or does not exist: " + rootPath) 80 } 81 82 isIncludeDir := false 83 if len(includeDir) >= 1 { 84 isIncludeDir = includeDir[0] 85 } 86 return statDir(rootPath, "", isIncludeDir, false) 87 } 88 89 // GetAllSubDirs returns all subdirectories of given root path. 90 // Slice does not include given path itself. 91 func GetAllSubDirs(rootPath string) ([]string, error) { 92 if !IsDir(rootPath) { 93 return nil, errors.New("not a directory or does not exist: " + rootPath) 94 } 95 return statDir(rootPath, "", true, true) 96 } 97 98 // CopyDir copy files recursively from source to target directory. 99 // 100 // The filter accepts a function that process the path info. 101 // and should return true for need to filter. 102 // 103 // It returns error when error occurs in underlying functions. 104 func CopyDir(srcPath, destPath string, filters ...func(filePath string) bool) error { 105 // Check if target directory exists. 106 if !IsExist(destPath) { 107 err := os.MkdirAll(destPath, os.ModePerm) 108 if err != nil { 109 return err 110 } 111 } 112 113 // Gather directory info. 114 infos, err := StatDir(srcPath, true) 115 if err != nil { 116 return err 117 } 118 119 var filter func(filePath string) bool 120 if len(filters) > 0 { 121 filter = filters[0] 122 } 123 124 for _, info := range infos { 125 if filter != nil && filter(info) { 126 continue 127 } 128 129 curPath := filepath.Join(destPath, info) 130 if strings.HasSuffix(info, "/") { 131 err = os.MkdirAll(curPath, os.ModePerm) 132 } else { 133 err = Copy(filepath.Join(srcPath, info), curPath) 134 } 135 if err != nil { 136 return err 137 } 138 } 139 return nil 140 } 141 142 func FindNotExistsDirs(dir string) ([]string, error) { 143 var notExistsDirs []string 144 oldParent := dir 145 parent := filepath.Dir(dir) 146 for oldParent != parent { 147 _, err := os.Stat(parent) 148 if err == nil { 149 break 150 } 151 if !os.IsNotExist(err) { 152 return notExistsDirs, err 153 } 154 notExistsDirs = append(notExistsDirs, parent) 155 oldParent = parent 156 parent = filepath.Dir(parent) 157 } 158 return notExistsDirs, nil 159 } 160 161 func MkdirAll(dir string, mode os.FileMode) error { 162 if fi, err := os.Stat(dir); err == nil { 163 if fi.IsDir() { 164 if fi.Mode().Perm() != mode.Perm() { 165 return os.Chmod(dir, mode) 166 } 167 return nil 168 } 169 } 170 needChmodDirs, err := FindNotExistsDirs(dir) 171 if err != nil { 172 return err 173 } 174 //Dump(needChmodDirs) 175 176 err = os.MkdirAll(dir, mode) 177 if err != nil { 178 return err 179 } 180 err = os.Chmod(dir, mode) 181 if err != nil { 182 return err 183 } 184 for _, dir := range needChmodDirs { 185 err = os.Chmod(dir, mode) 186 if err != nil { 187 return err 188 } 189 } 190 return err 191 }