252

Goの1つのディレクトリにあるファイルとフォルダを簡単に一覧表示する方法を見つけようとしています。

見つけましfilepath.Walkたが、自動的にサブディレクトリに入ります。これは望ましくありません。私の他のすべての検索は、何も良くなりませんでした。

この機能は確かに存在しますが、見つけるのは非常に困難です。誰かが私がどこを見るべきか知っているかどうか私に知らせてください。ありがとう。

4

7 に答える 7

430

パッケージ内のReadDir関数を使用してみることができio/ioutilます。ドキュメントによると:

ReadDirは、dirnameで指定されたディレクトリを読み取り、ソートされたディレクトリエントリのリストを返します。

結果のスライスには、ここos.FileInfoにリストされているメソッドを提供するタイプが含まれています。これは、現在のディレクトリ内のすべての名前を一覧表示する基本的な例です(フォルダは含まれていますが、特別にマークされていません。メソッドを使用して、アイテムがフォルダであるかどうかを確認できます)。IsDir()

package main

import (
    "fmt"
    "io/ioutil"
     "log"
)

func main() {
    files, err := ioutil.ReadDir("./")
    if err != nil {
        log.Fatal(err)
    }
 
    for _, f := range files {
            fmt.Println(f.Name())
    }
}
于 2013-02-03T02:29:44.983 に答える
96

さまざまなgolang標準ライブラリ関数を使用して、ファイルシステム上のフォルダ内のファイルのリストを取得できます。

  1. filepath.Walk
  2. ioutil.ReadDir
  3. os.File.Readdir

package main

import (
    "fmt"
    "io/ioutil"
    "log"
    "os"
    "path/filepath"
)

func main() {
    var (
        root  string
        files []string
        err   error
    )

    root := "/home/manigandan/golang/samples"
    // filepath.Walk
    files, err = FilePathWalkDir(root)
    if err != nil {
        panic(err)
    }
    // ioutil.ReadDir
    files, err = IOReadDir(root)
    if err != nil {
        panic(err)
    }
    //os.File.Readdir
    files, err = OSReadDir(root)
    if err != nil {
        panic(err)
    }

    for _, file := range files {
        fmt.Println(file)
    }
}
  1. filepath.Walkを使用する

このpath/filepathパッケージは、ディレクトリ内のすべてのファイルをスキャンする便利な方法を提供し、ディレクトリ内の各サブディレクトリを自動的にスキャンします。

func FilePathWalkDir(root string) ([]string, error) {
    var files []string
    err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
        if !info.IsDir() {
            files = append(files, path)
        }
        return nil
    })
    return files, err
}
  1. ioutil.ReadDirの使用

ioutil.ReadDirdirnameで指定されたディレクトリを読み取り、ファイル名でソートされたディレクトリエントリのリストを返します。

func IOReadDir(root string) ([]string, error) {
    var files []string
    fileInfo, err := ioutil.ReadDir(root)
    if err != nil {
        return files, err
    }

    for _, file := range fileInfo {
        files = append(files, file.Name())
    }
    return files, nil
}
  1. os.File.Readdirの使用

Readdirは、ファイルに関連付けられたディレクトリの内容を読み取り、Lstatによって返されるように、ディレクトリ順に最大n個のFileInfo値のスライスを返します。同じファイルに対する後続の呼び出しは、さらにFileInfoを生成します。

func OSReadDir(root string) ([]string, error) {
    var files []string
    f, err := os.Open(root)
    if err != nil {
        return files, err
    }
    fileInfo, err := f.Readdir(-1)
    f.Close()
    if err != nil {
        return files, err
    }

    for _, file := range fileInfo {
        files = append(files, file.Name())
    }
    return files, nil
}

ベンチマーク結果。

ベンチマークスコア

このブログ投稿で詳細を入手してください

于 2018-03-09T15:07:26.097 に答える
81

さらに簡単に、使用しますpath/filepath

package main    

import (
    "fmt"
    "log"
    "path/filepath"
)

func main() {
    files, err := filepath.Glob("*")
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(files) // contains a list of all files in the current directory
}
于 2013-08-20T07:04:23.470 に答える
23

ioutil.ReadDir良い発見ですが、ソースをクリックして見ると、os.FileのメソッドReaddirを呼び出していることがわかります。ディレクトリの順序に問題がなく、リストを並べ替える必要がない場合は、このReaddirメソッドで十分です。

于 2013-02-03T11:58:22.823 に答える
17

Go 1.16以降では、os.ReadDir関数を使用できます。

func ReadDir(name string) ([]DirEntry, error)

DirEntry指定されたディレクトリを読み取り、ファイル名でソートされたディレクトリエントリを含むスライスを返します。

これは楽観的な関数であるため、ディレクトリエントリの読み取り中にエラーが発生すると、エラーの前の時点までのファイル名を含むスライスが返されます。

package main

import (
    "fmt"
    "log"
    "os"
)

func main() {
    files, err := os.ReadDir(".")
    if err != nil {
        log.Fatal(err)
    }

    for _, file := range files {
        fmt.Println(file.Name())
    }
}

興味深い:Go 1.17(Q3 2021)には以下が含まれますfs.FileInfoToDirEntry()

func FileInfoToDirEntry(info FileInfo) DirEntry

FileInfoToDirEntryDirEntryから情報を返すを返しますinfo。がnilの
場合、nilを返します。infoFileInfoToDirEntry


バックグラウンド

Go 1.16(Q1 2021)は、CL243908およびCL243914を使用して、インターフェイスに基づいたReadDir関数を提案します。FS

// An FS provides access to a hierarchical file system.
//
// The FS interface is the minimum implementation required of the file system.
// A file system may implement additional interfaces,
// such as fsutil.ReadFileFS, to provide additional or optimized functionality.
// See io/fsutil for details.
type FS interface {
    // Open opens the named file.
    //
    // When Open returns an error, it should be of type *PathError
    // with the Op field set to "open", the Path field set to name,
    // and the Err field describing the problem.
    //
    // Open should reject attempts to open names that do not satisfy
    // ValidPath(name), returning a *PathError with Err set to
    // ErrInvalid or ErrNotExist.
    Open(name string) (File, error)
}

これにより、「os:軽量ディレクトリ読み取り用のメソッドの追加」ReadDir可能になります。commita4ede9f
を参照してください。

// ReadDir reads the contents of the directory associated with the file f
// and returns a slice of DirEntry values in directory order.
// Subsequent calls on the same file will yield later DirEntry records in the directory.
//
// If n > 0, ReadDir returns at most n DirEntry records.
// In this case, if ReadDir returns an empty slice, it will return an error explaining why.
// At the end of a directory, the error is io.EOF.
//
// If n <= 0, ReadDir returns all the DirEntry records remaining in the directory.
// When it succeeds, it returns a nil error (not io.EOF).
func (f *File) ReadDir(n int) ([]DirEntry, error) 

// A DirEntry is an entry read from a directory (using the ReadDir method).
type DirEntry interface {
    // Name returns the name of the file (or subdirectory) described by the entry.
    // This name is only the final element of the path, not the entire path.
    // For example, Name would return "hello.go" not "/home/gopher/hello.go".
    Name() string
    
    // IsDir reports whether the entry describes a subdirectory.
    IsDir() bool
    
    // Type returns the type bits for the entry.
    // The type bits are a subset of the usual FileMode bits, those returned by the FileMode.Type method.
    Type() os.FileMode
    
    // Info returns the FileInfo for the file or subdirectory described by the entry.
    // The returned FileInfo may be from the time of the original directory read
    // or from the time of the call to Info. If the file has been removed or renamed
    // since the directory read, Info may return an error satisfying errors.Is(err, ErrNotExist).
    // If the entry denotes a symbolic link, Info reports the information about the link itself,
    // not the link's target.
    Info() (FileInfo, error)
}

src/os/os_test.go#testReadDir()その使用法を示しています。

    file, err := Open(dir)
    if err != nil {
        t.Fatalf("open %q failed: %v", dir, err)
    }
    defer file.Close()
    s, err2 := file.ReadDir(-1)
    if err2 != nil {
        t.Fatalf("ReadDir %q failed: %v", dir, err2)
    }

Ben Hoytは、Go1.16へのコメントで指摘していos.ReadDirます。

os.ReadDir(path string) ([]os.DirEntry, error)Open、ダンスなしで直接呼び出すことができます。
したがって、これを単純に短縮することができます。これはos.ReadDir、ほとんどの人が呼び出す具体的な関数です。

コミット3d913a9(2020年12月)を参照してください。

os:add 、、ReadFile(was )、WriteFile(was )fromCreateTempTempFileMkdirTempTempDirio/ioutil

io/ioutil不十分に定義されたヘルパーのコレクションでした。

提案#40025は、汎用I/Oヘルパーをioに移動しました。提案#42026のこのCLは、OS固有のヘルパーをに移動し、パッケージos全体io/ioutilを非推奨にします。

os.ReadDir's[]DirEntryとは対照的に、を返します。 (戻るヘルパーを提供することは、この変更の主な動機の1つです。)ioutil.ReadDir[]FileInfo
[]DirEntry

于 2020-10-20T11:07:03.053 に答える
14

説明から、おそらく必要なのはos.Readdirnamesです。

func (f *File) Readdirnames(n int) (names []string, err error)

Readdirnamesは、ファイルに関連付けられているディレクトリの内容を読み取り、ディレクトリ内の最大n個のファイル名のスライスをディレクトリ順に返します。同じファイルに対する後続の呼び出しは、さらに名前を生成します。

..。

n <= 0の場合、Readdirnamesは、ディレクトリからすべての名前を1つのスライスで返します。

スニペット:

file, err := os.Open(path)
if err != nil {
    return err
}
defer file.Close()
names, err := file.Readdirnames(0)
if err != nil {
    return err
}
fmt.Println(names)

SquattingSlavInTracksuitコメントへのクレジット; できれば、彼らのコメントを回答に昇格させることを提案したでしょう。

于 2020-02-03T18:49:59.067 に答える
1

ディレクトリ内のすべてのファイルを再帰的に使用して印刷する完全な例Readdirnames

package main

import (
    "fmt"
    "os"
)

func main() {
    path := "/path/to/your/directory"
    err := readDir(path)
    if err != nil {
        panic(err)
    }
}

func readDir(path string) error {
    file, err := os.Open(path)
    if err != nil {
        return err
    }
    defer file.Close()
    names, _ := file.Readdirnames(0)
    for _, name := range names {
        filePath := fmt.Sprintf("%v/%v", path, name)
        file, err := os.Open(filePath)
        if err != nil {
            return err
        }
        defer file.Close()
        fileInfo, err := file.Stat()
        if err != nil {
            return err
        }
        fmt.Println(filePath)
        if fileInfo.IsDir() {
            readDir(filePath)
        }
    }
    return nil
}
于 2021-11-12T14:33:27.647 に答える