dir.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  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. package com
  15. import (
  16. "errors"
  17. "fmt"
  18. "os"
  19. "path"
  20. "strings"
  21. )
  22. // IsDir returns true if given path is a directory,
  23. // or returns false when it's a file or does not exist.
  24. func IsDir(dir string) bool {
  25. f, e := os.Stat(dir)
  26. if e != nil {
  27. return false
  28. }
  29. return f.IsDir()
  30. }
  31. func statDir(dirPath, recPath string, includeDir, isDirOnly bool) ([]string, error) {
  32. dir, err := os.Open(dirPath)
  33. if err != nil {
  34. return nil, err
  35. }
  36. defer dir.Close()
  37. fis, err := dir.Readdir(0)
  38. if err != nil {
  39. return nil, err
  40. }
  41. statList := make([]string, 0)
  42. for _, fi := range fis {
  43. if strings.Contains(fi.Name(), ".DS_Store") {
  44. continue
  45. }
  46. relPath := path.Join(recPath, fi.Name())
  47. curPath := path.Join(dirPath, fi.Name())
  48. if fi.IsDir() {
  49. if includeDir {
  50. statList = append(statList, relPath+"/")
  51. }
  52. s, err := statDir(curPath, relPath, includeDir, isDirOnly)
  53. if err != nil {
  54. return nil, err
  55. }
  56. statList = append(statList, s...)
  57. } else if !isDirOnly {
  58. statList = append(statList, relPath)
  59. }
  60. }
  61. return statList, nil
  62. }
  63. // StatDir gathers information of given directory by depth-first.
  64. // It returns slice of file list and includes subdirectories if enabled;
  65. // it returns error and nil slice when error occurs in underlying functions,
  66. // or given path is not a directory or does not exist.
  67. //
  68. // Slice does not include given path itself.
  69. // If subdirectories is enabled, they will have suffix '/'.
  70. func StatDir(rootPath string, includeDir ...bool) ([]string, error) {
  71. if !IsDir(rootPath) {
  72. return nil, errors.New("not a directory or does not exist: " + rootPath)
  73. }
  74. isIncludeDir := false
  75. if len(includeDir) >= 1 {
  76. isIncludeDir = includeDir[0]
  77. }
  78. return statDir(rootPath, "", isIncludeDir, false)
  79. }
  80. // GetAllSubDirs returns all subdirectories of given root path.
  81. // Slice does not include given path itself.
  82. func GetAllSubDirs(rootPath string) ([]string, error) {
  83. if !IsDir(rootPath) {
  84. return nil, errors.New("not a directory or does not exist: " + rootPath)
  85. }
  86. return statDir(rootPath, "", true, true)
  87. }
  88. // GetFileListBySuffix returns an ordered list of file paths.
  89. // It recognize if given path is a file, and don't do recursive find.
  90. func GetFileListBySuffix(dirPath, suffix string) ([]string, error) {
  91. if !IsExist(dirPath) {
  92. return nil, fmt.Errorf("given path does not exist: %s", dirPath)
  93. } else if IsFile(dirPath) {
  94. return []string{dirPath}, nil
  95. }
  96. // Given path is a directory.
  97. dir, err := os.Open(dirPath)
  98. if err != nil {
  99. return nil, err
  100. }
  101. fis, err := dir.Readdir(0)
  102. if err != nil {
  103. return nil, err
  104. }
  105. files := make([]string, 0, len(fis))
  106. for _, fi := range fis {
  107. if strings.HasSuffix(fi.Name(), suffix) {
  108. files = append(files, path.Join(dirPath, fi.Name()))
  109. }
  110. }
  111. return files, nil
  112. }
  113. // CopyDir copy files recursively from source to target directory.
  114. //
  115. // The filter accepts a function that process the path info.
  116. // and should return true for need to filter.
  117. //
  118. // It returns error when error occurs in underlying functions.
  119. func CopyDir(srcPath, destPath string, filters ...func(filePath string) bool) error {
  120. // Check if target directory exists.
  121. if IsExist(destPath) {
  122. return errors.New("file or directory alreay exists: " + destPath)
  123. }
  124. err := os.MkdirAll(destPath, os.ModePerm)
  125. if err != nil {
  126. return err
  127. }
  128. // Gather directory info.
  129. infos, err := StatDir(srcPath, true)
  130. if err != nil {
  131. return err
  132. }
  133. var filter func(filePath string) bool
  134. if len(filters) > 0 {
  135. filter = filters[0]
  136. }
  137. for _, info := range infos {
  138. if filter != nil && filter(info) {
  139. continue
  140. }
  141. curPath := path.Join(destPath, info)
  142. if strings.HasSuffix(info, "/") {
  143. err = os.MkdirAll(curPath, os.ModePerm)
  144. } else {
  145. err = Copy(path.Join(srcPath, info), curPath)
  146. }
  147. if err != nil {
  148. return err
  149. }
  150. }
  151. return nil
  152. }