| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137 |
- package sftp
- import (
- "path"
- "strings"
- )
- // ErrBadPattern indicates a globbing pattern was malformed.
- var ErrBadPattern = path.ErrBadPattern
- // Match reports whether name matches the shell pattern.
- //
- // This is an alias for path.Match from the standard library,
- // offered so that callers need not import the path package.
- // For details, see https://golang.org/pkg/path/#Match.
- func Match(pattern, name string) (matched bool, err error) {
- return path.Match(pattern, name)
- }
- // detect if byte(char) is path separator
- func isPathSeparator(c byte) bool {
- return c == '/'
- }
- // Split splits the path p immediately following the final slash,
- // separating it into a directory and file name component.
- //
- // This is an alias for path.Split from the standard library,
- // offered so that callers need not import the path package.
- // For details, see https://golang.org/pkg/path/#Split.
- func Split(p string) (dir, file string) {
- return path.Split(p)
- }
- // Glob returns the names of all files matching pattern or nil
- // if there is no matching file. The syntax of patterns is the same
- // as in Match. The pattern may describe hierarchical names such as
- // /usr/*/bin/ed.
- //
- // Glob ignores file system errors such as I/O errors reading directories.
- // The only possible returned error is ErrBadPattern, when pattern
- // is malformed.
- func (c *Client) Glob(pattern string) (matches []string, err error) {
- if !hasMeta(pattern) {
- file, err := c.Lstat(pattern)
- if err != nil {
- return nil, nil
- }
- dir, _ := Split(pattern)
- dir = cleanGlobPath(dir)
- return []string{Join(dir, file.Name())}, nil
- }
- dir, file := Split(pattern)
- dir = cleanGlobPath(dir)
- if !hasMeta(dir) {
- return c.glob(dir, file, nil)
- }
- // Prevent infinite recursion. See issue 15879.
- if dir == pattern {
- return nil, ErrBadPattern
- }
- var m []string
- m, err = c.Glob(dir)
- if err != nil {
- return
- }
- for _, d := range m {
- matches, err = c.glob(d, file, matches)
- if err != nil {
- return
- }
- }
- return
- }
- // cleanGlobPath prepares path for glob matching.
- func cleanGlobPath(path string) string {
- switch path {
- case "":
- return "."
- case "/":
- return path
- default:
- return path[0 : len(path)-1] // chop off trailing separator
- }
- }
- // glob searches for files matching pattern in the directory dir
- // and appends them to matches. If the directory cannot be
- // opened, it returns the existing matches. New matches are
- // added in lexicographical order.
- func (c *Client) glob(dir, pattern string, matches []string) (m []string, e error) {
- m = matches
- fi, err := c.Stat(dir)
- if err != nil {
- return
- }
- if !fi.IsDir() {
- return
- }
- names, err := c.ReadDir(dir)
- if err != nil {
- return
- }
- //sort.Strings(names)
- for _, n := range names {
- matched, err := Match(pattern, n.Name())
- if err != nil {
- return m, err
- }
- if matched {
- m = append(m, Join(dir, n.Name()))
- }
- }
- return
- }
- // Join joins any number of path elements into a single path, separating
- // them with slashes.
- //
- // This is an alias for path.Join from the standard library,
- // offered so that callers need not import the path package.
- // For details, see https://golang.org/pkg/path/#Join.
- func Join(elem ...string) string {
- return path.Join(elem...)
- }
- // hasMeta reports whether path contains any of the magic characters
- // recognized by Match.
- func hasMeta(path string) bool {
- return strings.ContainsAny(path, "\\*?[")
- }
|