Skip to content

Instantly share code, notes, and snippets.

@devi
Created May 16, 2013 17:03
Show Gist options
  • Save devi/5593302 to your computer and use it in GitHub Desktop.
Save devi/5593302 to your computer and use it in GitHub Desktop.
list files in a directory
// list files in a directory
// code adapted from github.com/replicon/fast-archiver
package main
import (
"fmt"
"log"
"os"
"io"
"sync"
"path/filepath"
"time"
"flag"
)
type MyScanner struct {
Recursive bool
dirChan chan string
fileChan chan string
syncWorker sync.WaitGroup
}
func (m *MyScanner) Run(path string) {
t0 := time.Now()
m.dirChan = make(chan string)
m.fileChan = make(chan string)
m.syncWorker.Add(1)
go func(){ m.dirChan <- path }()
go m.scanDir()
go func(){
m.syncWorker.Wait()
close(m.dirChan)
close(m.fileChan)
}()
total := 0
for filename := range m.fileChan {
fmt.Println(filename)
total++
}
t1 := time.Now()
fmt.Printf("%d files scanned in %v\n", total, t1.Sub(t0))
}
func (m *MyScanner) scanDir() {
for path := range m.dirChan {
dir, err := os.Open(path)
if err != nil {
log.Println("directory read error:", err)
m.syncWorker.Done()
continue
}
for fileName := range m.readdirnames(dir) {
filePath := filepath.Join(path, fileName)
fileInfo, err := os.Lstat(filePath)
if err != nil {
log.Println("unable to lstat file", err.Error())
continue
} else if (fileInfo.Mode() & os.ModeSymlink) != 0 {
log.Println("skipping symbolic link", filePath)
continue
}
if fileInfo.IsDir() && m.Recursive {
m.syncWorker.Add(1)
go func(filePath string) {
m.dirChan <- filePath
}(filePath)
} else {
m.fileChan <- filePath
}
}
dir.Close()
m.syncWorker.Done()
}
}
func (m *MyScanner) readdirnames(dir *os.File) chan string {
retval := make(chan string, 256)
go func(dir *os.File) {
for {
names, err := dir.Readdirnames(256)
if err == io.EOF {
break
} else if err != nil {
log.Println("error reading directory:", err.Error())
}
for _, name := range names {
retval <- name
}
}
close(retval)
}(dir)
return retval
}
var baseDir = flag.String("p", "", "/path/to/the/directory")
func main() {
flag.Parse()
if *baseDir == "" {
flag.PrintDefaults()
os.Exit(1)
}
(&MyScanner{Recursive: true}).Run(*baseDir)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment