답변:
편집 : 충분한 사람들이 여전히이 답변을 쳤으므로 Go1 API에 대해 업데이트 할 것이라고 생각했습니다. 이것은 filepath.Walk () 의 작동 예제입니다 . 원본은 아래와 같습니다.
package main
import (
"path/filepath"
"os"
"flag"
"fmt"
)
func visit(path string, f os.FileInfo, err error) error {
fmt.Printf("Visited: %s\n", path)
return nil
}
func main() {
flag.Parse()
root := flag.Arg(0)
err := filepath.Walk(root, visit)
fmt.Printf("filepath.Walk() returned %v\n", err)
}
filepath.Walk는 디렉토리 트리를 재귀 적으로 탐색합니다.
다음은 실행 예입니다.
$ mkdir -p dir1/dir2
$ touch dir1/file1 dir1/dir2/file2
$ go run walk.go dir1
Visited: dir1
Visited: dir1/dir2
Visited: dir1/dir2/file2
Visited: dir1/file1
filepath.Walk() returned <nil>
원래 답변 : 걷기 파일 경로의 인터페이스가 매주 변경되었습니다 . 2011-09-16, http://groups.google.com/group/golang-nuts/msg/e304dd9cf196a218을 참조하세요 . 아래 코드는 가까운 시일 내에 GO 릴리스 버전에서 작동하지 않습니다.
실제로 이것을위한 표준 lib에는 filepath.Walk 함수가 있습니다.
package main
import (
"path/filepath"
"os"
"flag"
)
type visitor int
// THIS CODE NO LONGER WORKS, PLEASE SEE ABOVE
func (v visitor) VisitDir(path string, f *os.FileInfo) bool {
println(path)
return true
}
func (v visitor) VisitFile(path string, f *os.FileInfo) {
println(path)
}
func main() {
root := flag.Arg(0)
filepath.Walk(root, visitor(0), nil)
}
filepath.Walk
그런데 심볼릭 링크를 따르지 않습니다.
filepath.Walk
콜백은 심볼릭 링크 (파일과 디렉토리 모두)에서 트리거됩니다. 예 , 그것들을 따르지 않을 것이지만 콜백은 심볼릭 링크를 인식하고 추가 조치를 취 filepath.Walk
합니다.
다음은 디렉토리의 파일에 대한 파일 정보를 얻는 방법입니다.
package main
import (
"fmt"
"os"
"path/filepath"
)
func main() {
dirname := "." + string(filepath.Separator)
d, err := os.Open(dirname)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
defer d.Close()
fi, err := d.Readdir(-1)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
for _, fi := range fi {
if fi.Mode().IsRegular() {
fmt.Println(fi.Name(), fi.Size(), "bytes")
}
}
}
Readdir
메소드 매개 변수입니다 . 만약 , 모든 반환 한 조각의 디렉토리. n
int
n <= 0
Readdir
FileInfo
os
func (FileMode) IsRegular
.
다음은 모든 파일과 디렉토리를 재귀 적으로 반복하는 예제입니다. 추가하려는 경로가 디렉토리인지 알고 싶다면 "f.IsDir ()"을 확인하십시오.
package main
import (
"fmt"
"os"
"path/filepath"
)
func main() {
searchDir := "c:/path/to/dir"
fileList := []string{}
err := filepath.Walk(searchDir, func(path string, f os.FileInfo, err error) error {
fileList = append(fileList, path)
return nil
})
for _, file := range fileList {
fmt.Println(file)
}
}
main
방법은하지 말았어야 ([]string, error)
인수를 당신이 뭔가를 할 필요가 err
. 답변 당시 유효하지 않은 경우? 최신 버전에서는 확실히 컴파일 오류입니다. 그렇지 않으면 매우 유용합니다. 감사합니다.
패키지 github.com/kr/fs
는 Walker
매우 흥미로운 API를 제공합니다 .
Go 표준 패키지 ioutil
에는이 사례 시나리오에 대한 기능이 내장되어 있습니다 (아래 예제 참조).
func searchFiles(dir string) { // dir is the parent directory you what to search
files, err := ioutil.ReadDir(dir)
if err != nil {
log.Fatal(err)
}
for _, file := range files {
fmt.Println(file.Name())
}
}
"Walk는 심볼릭 링크를 따르지 않습니다."라는 점에 유의하십시오. 그렇게하는 함수를 작성하려는 경우 ioutil.ReadDir을 권장 합니다 . 내 벤치 마크 테스트에 따르면 파일 경로 보다 빠르고 메모리 사용량이 적습니다. .
또한 ioutil.ReadDir
기본 문자열 비교 ( strA > strB
)를 사용하여 기본 이름별로 파일을 정렬합니다 . devops 녀석으로서 저는 일반적으로 역 수치 비교를 수행하여 dir 이름을 정렬합니다 (예 : 최신 빌드 먼저). 그것이 또한 당신의 경우라면 os.ReadDir을 직접 ioutil.ReadDir
호출하고 (이를 커버 아래에서 호출하고 있음) 직접 정렬 하는 것이 좋습니다 .
다음은 ReadDir
숫자 정렬 을 사용하는 부품 의 예입니다 .
// ReadDirNumSort - Same as ioutil/ReadDir but uses returns a Numerically
// Sorted file list.
//
// Taken from https://golang.org/src/io/ioutil/ioutil.go
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//
// Modified Sort method to use Numerically sorted names instead.
// It also allows reverse sorting.
func ReadDirNumSort(dirname string, reverse bool) ([]os.FileInfo, error) {
f, err := os.Open(dirname)
if err != nil {
return nil, err
}
list, err := f.Readdir(-1)
f.Close()
if err != nil {
return nil, err
}
if reverse {
sort.Sort(sort.Reverse(byName(list)))
} else {
sort.Sort(byName(list))
}
return list, nil
}
// byName implements sort.Interface.
type byName []os.FileInfo
func (f byName) Len() int { return len(f) }
func (f byName) Swap(i, j int) { f[i], f[j] = f[j], f[i] }
func (f byName) Less(i, j int) bool {
nai, err := strconv.Atoi(f[i].Name())
if err != nil {
return f[i].Name() < f[j].Name()
}
naj, err := strconv.Atoi(f[j].Name())
if err != nil {
return f[i].Name() < f[j].Name()
}
return nai < naj
}
여기에서 기능 카레를 할 수 있으므로 검색을 충분히 활용할 수 있습니다.
func visit(files *[]string) filepath.WalkFunc {
return func (path string, info os.FileInfo, err error) error {
// maybe do this in some if block
*files = append(*files, path)
return nil
}
}