github.com/scottcagno/storage@v1.8.0/pkg/filesystem/ls.go (about) 1 package filesystem 2 3 import ( 4 "flag" 5 "fmt" 6 "io/fs" 7 "os" 8 "path/filepath" 9 "sort" 10 "strings" 11 ) 12 13 var showAll = flag.Bool("a", false, "flag to output all files") 14 var showLong = flag.Bool("l", false, "flag to output long format") 15 var sortModTime = flag.Bool("t", false, "flag to sort output by modification time") 16 var sortSize = flag.Bool("s", false, "flag to sort output by size") 17 18 func LSCli() { 19 // parse flags 20 flag.Parse() 21 // if no file was given, copy stdin to stdout 22 if flag.NArg() == 0 { 23 ls(".") 24 return 25 } 26 // otherwise, a file was given, so use that as input 27 ls(flag.Arg(0)) 28 } 29 30 func LS(dir string) { 31 if dir == "" { 32 dir = "." 33 } 34 ls(dir) 35 } 36 37 const doNotSkip bool = false 38 39 func ls(dir string) { 40 // skip function 41 skip := func(de fs.DirEntry) bool { 42 return doNotSkip 43 } 44 // setup listing 45 var listing []fs.DirEntry 46 // walk dir path 47 err := filepath.WalkDir(dir, func(path string, de fs.DirEntry, err error) error { 48 if err != nil { 49 fmt.Fprintf(os.Stderr, "prevent panic by handling failure accessing a path %q: %v\n", path, err) 50 return err 51 } 52 if skip(de) { 53 return fs.SkipDir 54 } 55 if canPrint(de) { 56 listing = append(listing, de) 57 //fmt.Fprintf(os.Stdout, "%s", fmtEntry(de)) 58 } 59 return nil 60 }) 61 // check for errors 62 if err != nil { 63 fmt.Fprintf(os.Stderr, "%s", err) 64 } 65 // finish 66 printListing(listing) 67 if !*showLong { 68 fmt.Println() 69 } 70 } 71 72 func canPrint(de fs.DirEntry) bool { 73 if *showAll { 74 return true 75 } 76 return !strings.HasPrefix(de.Name(), ".") 77 } 78 79 func fmtEntry(de fs.DirEntry) string { 80 if *showLong { 81 return fmt.Sprintf("%s\n", de.Name()) 82 } 83 return fmt.Sprintf("%s ", de.Name()) 84 } 85 86 func printListing(listing []fs.DirEntry) { 87 if *sortSize { 88 By(size).Sort(listing) 89 } 90 if *sortModTime { 91 By(modtime).Sort(listing) 92 } 93 for _, de := range listing { 94 fmt.Fprintf(os.Stdout, "%s", fmtEntry(de)) 95 } 96 } 97 98 var size = func(d1, d2 fs.DirEntry) bool { 99 d1i, err := d1.Info() 100 if err != nil { 101 fmt.Fprintf(os.Stderr, "%s", err) 102 } 103 d2i, err := d2.Info() 104 if err != nil { 105 fmt.Fprintf(os.Stderr, "%s", err) 106 } 107 return d1i.Size() > d2i.Size() 108 } 109 110 var modtime = func(d1, d2 fs.DirEntry) bool { 111 d1i, err := d1.Info() 112 if err != nil { 113 fmt.Fprintf(os.Stderr, "%s", err) 114 } 115 d2i, err := d2.Info() 116 if err != nil { 117 fmt.Fprintf(os.Stderr, "%s", err) 118 } 119 return d1i.ModTime().UnixNano() > d2i.ModTime().UnixNano() 120 } 121 122 type dirEntrySorter struct { 123 entries []fs.DirEntry 124 by func(e1, e2 fs.DirEntry) bool 125 } 126 127 func (des *dirEntrySorter) Len() int { 128 return len(des.entries) 129 } 130 131 func (des *dirEntrySorter) Swap(i, j int) { 132 des.entries[i], des.entries[j] = des.entries[j], des.entries[i] 133 } 134 135 func (des *dirEntrySorter) Less(i, j int) bool { 136 return des.by(des.entries[i], des.entries[j]) 137 } 138 139 type By func(e1, e2 fs.DirEntry) bool 140 141 func (by By) Sort(entries []fs.DirEntry) { 142 des := &dirEntrySorter{ 143 entries: entries, 144 by: by, 145 } 146 sort.Sort(des) 147 }