github.com/jxskiss/gopkg/v2@v2.14.9-0.20240514120614-899f3e7952b4/easy/filepath.go (about)

     1  package easy
     2  
     3  import (
     4  	"os"
     5  	"path/filepath"
     6  	"strings"
     7  )
     8  
     9  // Glob adds double-star support to the std library's [path/filepath.Glob].
    10  // It's useful when your pattern might have double-stars.
    11  func Glob(pattern string) (matches []string, err error) {
    12  	if !strings.Contains(pattern, "**") {
    13  		// Pass-through to std lib if no double-star.
    14  		return filepath.Glob(pattern)
    15  	}
    16  	parts := strings.Split(pattern, "**")
    17  	return globParts(parts).Expand()
    18  }
    19  
    20  type globParts []string
    21  
    22  func (globs globParts) Expand() (matches []string, err error) {
    23  	matches = []string{""}
    24  	for i, glob := range globs {
    25  		isLast := i == len(globs)-1
    26  		var hits []string
    27  		var seen = make(map[string]bool)
    28  		for _, match := range matches {
    29  			paths, err := filepath.Glob(match + glob)
    30  			if err != nil {
    31  				return nil, err
    32  			}
    33  			for _, path := range paths {
    34  				err = filepath.Walk(path, func(path string, info os.FileInfo, err error) error {
    35  					if err != nil {
    36  						return err
    37  					}
    38  					if isLast || info.IsDir() {
    39  						if _, ok := seen[path]; !ok {
    40  							hits = append(hits, path)
    41  							seen[path] = true
    42  						}
    43  					}
    44  					return nil
    45  				})
    46  				if err != nil {
    47  					return nil, err
    48  				}
    49  			}
    50  		}
    51  		matches = hits
    52  	}
    53  
    54  	if len(globs) == 0 && len(matches) > 0 && matches[0] == "" {
    55  		matches = matches[1:]
    56  	}
    57  
    58  	return matches, nil
    59  }
    60  
    61  // CreateNonExistingFolder checks whether a directory exists,
    62  // the directory will be created by calling `os.MkdirAll(path, perm)`
    63  // if it does not exist.
    64  func CreateNonExistingFolder(path string, perm os.FileMode) error {
    65  	if perm == 0 {
    66  		perm = 0o700
    67  	}
    68  	if _, err := os.Stat(path); os.IsNotExist(err) {
    69  		return os.MkdirAll(path, perm)
    70  	} else if err != nil {
    71  		return err
    72  	}
    73  	return nil
    74  }
    75  
    76  // WriteFile writes data to the named file, creating it if necessary.
    77  // If the file does not exist, WriteFile creates it with permissions perm (before umask);
    78  // otherwise WriteFile truncates it before writing, without changing permissions.
    79  //
    80  // If creates the directory if it does not exist instead of reporting an error.
    81  func WriteFile(name string, data []byte, perm os.FileMode) error {
    82  	dirPerm := getDirectoryPermFromFilePerm(perm)
    83  	err := CreateNonExistingFolder(filepath.Dir(name), dirPerm)
    84  	if err != nil {
    85  		return err
    86  	}
    87  	return os.WriteFile(name, data, perm)
    88  }
    89  
    90  func getDirectoryPermFromFilePerm(filePerm os.FileMode) os.FileMode {
    91  	var dirPerm os.FileMode = 0o700
    92  	if filePerm&0o060 > 0 {
    93  		dirPerm |= (filePerm & 0o070) | 0o010
    94  	}
    95  	if filePerm&0o006 > 0 {
    96  		dirPerm |= (filePerm & 0o007) | 0x001
    97  	}
    98  	return dirPerm
    99  }