- Bir klasörün yolu verildiğinde, o klasörde bulunan dosyaları tarayan bir işlev yazmam gerekiyor.
- Ve sonra o klasördeki dizin yapısını görüntülemem gerekiyor.
2'nin nasıl yapılacağını biliyorum (tarayıcıda görüntülemek için jstree kullanacağım).
2'nin nasıl yapılacağını biliyorum (tarayıcıda görüntülemek için jstree kullanacağım).
Yanıtlar:
DÜZENLEME : Yeterince kişi hala bu yanıta ulaşıyor, Go1 API için güncelleyeceğimi düşündüm. Bu, filepath.Walk () için çalışan bir örnektir . Orijinal aşağıda.
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)
}
Lütfen filepath.Walk'un dizin ağacını yinelemeli olarak yürüdüğünü unutmayın.
Bu bir örnek çalışma:
$ 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>
ORİJİNAL YANIT AŞAĞIDAKİ: Yürüme dosya yolları için arayüz weekly.2011-09-16 itibariyle değişti, bkz http://groups.google.com/group/golang-nuts/msg/e304dd9cf196a218 . Aşağıdaki kod yakın gelecekte GO'nun yayın sürümleri için çalışmayacaktır.
Aslında standart kitaplıkta bunun için bir işlev vardır: 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
bu arada sembolik bağlantıları takip etmiyor.
filepath.Walk
geri arama sembolik bağlantılarda (hem dosya hem de dizin) tetiklenecektir. Evet , onları takip etmeyecek, ancak geri arama bir sembolik bağlantıyı tanır ve daha fazla eylemde bulunur, yani filepath.Walk
ilk önce yolun daha önce ziyaret edilmediğini garanti eden bir takip .
Bir dizindeki dosyalar için dosya bilgilerini elde etmenin bir yolu.
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
yöntem parametresi n
bir int
. If n <= 0
, dizindeki Readdir
tüm FileInfo
öğeleri tek bir dilimde döndürür .
os
func (FileMode) IsRegular
.
İşte tüm dosya ve dizinlerde özyinelemeli döngü için bir örnek. Eklediğiniz yolun bir dizin olup olmadığını öğrenmek istiyorsanız, sadece "f.IsDir ()" seçeneğini işaretleyin.
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
Yöntem olmamalıdır ([]string, error)
args ve birlikte bir şeyler yapmak gerekiyor err
. Cevap verildiği sırada geçerli olmadığı sürece? Daha yeni sürümlerde kesinlikle bir derleme hatası. Aksi takdirde, çok faydalı, teşekkürler.
Paket github.com/kr/fs
, Walker
çok ilginç bir API ile bir sağlar .
Go standard paketi ioutil
bu durum senaryosu için yerleşik işleve sahiptir, aşağıdaki örneğe bakın
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 sembolik bağları izlemez ", bu nedenle ioutil.ReadDir'i önerdiğim bir işlev yazmak istiyorsanız, unutmayın . Kendi kıyaslama testim , filepath.Glob'dan daha hızlı ve daha az bellek yoğun olduğunu gösterdi .
Ek olarak, ioutil.ReadDir
dosyaları temel dize karşılaştırması ( strA > strB
) kullanarak taban adına göre sıralar . Bir devops adamı olarak, genellikle ters sayısal bir karşılaştırma yaparak dir isimlerini sıralarım (örneğin en son derleme). Bu da sizin durumunuzsa, os.ReadDir'i doğrudan ioutil.ReadDir
çağırmak ( bunu kapakların altında çağırmaktır) ve sıralamayı kendiniz yapmak daha iyidir .
İşte ReadDir
Sayısal sıralama ile parçanın bir örneği :
// 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
}
Aramayı tam olarak kullanabilmek için burada currying işlevi yapmak isteyebilirsiniz.
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
}
}