最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Golang遞歸獲取目錄下所有文件方法實(shí)例

 更新時(shí)間:2023年02月27日 09:17:44   作者:戀喵大鯉魚(yú)  
這篇文章主要給大家介紹了關(guān)于Golang遞歸獲取目錄下所有文件的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下

1.問(wèn)題

如果我想獲取一個(gè)目錄下的所有文件列表,使用 Golang 該如何實(shí)現(xiàn)呢?

比如有個(gè)目錄 dir 結(jié)構(gòu)如下:

tree dir
dir
├── bar.txt
├── foo.txt
└── subdir
    └── baz.txt

那么如何獲取 dir 目錄下的所有文件路徑呢?

dir/foo.txt
dir/bar.txt
dir/subdir/baz.txt

2.io/ioutil

標(biāo)準(zhǔn)庫(kù) io/ioutil 包提供了一個(gè)函數(shù) ReadDir() 可以獲取指定目錄下的所有內(nèi)容,按文件名排序,返回 []fs.FileInfo 切片來(lái)描述目錄中的所有內(nèi)容。

func ReadDir(dirname string) ([]fs.FileInfo, error)

利用 ioutil.ReadDir() 我們可以獲取目錄中的所有文件嗎?

// ListDir lists all the file or dir names in the specified directory.
// Note that ListDir don't traverse recursively.
func ListDir(dirname string) ([]string, error) {
	infos, err := ioutil.ReadDir(dirname)
	if err != nil {
		return nil, err
	}
	names := make([]string, len(infos))
	for i, info := range infos {
		names[i] = info.Name()
	}
	return names, nil
}

我們來(lái)測(cè)試一下:

package main

import (
	"fmt"
	"io/ioutil"
)

func main() {
	names, _ := ListDir("dir")
	fmt.Printf("names:%v\n", names)
}

運(yùn)行輸出:

names:[bar.txt foo.txt subdir]

可見(jiàn) ioutil.ReadDir() 并不會(huì)遞歸獲取子目錄的內(nèi)容。

3.遞歸獲取

如果想遞歸獲子目錄的內(nèi)容,該如何實(shí)現(xiàn)呢?

我們可以遞歸的調(diào)用我們自己的函數(shù),來(lái)遞歸遍歷子目錄。

// GetDirAllFilePaths gets all the file paths in the specified directory recursively.
func GetDirAllFilePaths(dirname string) ([]string, error) {
	// Remove the trailing path separator if dirname has.
	dirname = strings.TrimSuffix(dirname, string(os.PathSeparator))

	infos, err := ioutil.ReadDir(dirname)
	if err != nil {
		return nil, err
	}

	paths := make([]string, 0, len(infos))
	for _, info := range infos {
		path := dirname + string(os.PathSeparator) + info.Name()
		if info.IsDir() {
			tmp, err := GetDirAllFilePaths(path)
			if err != nil {
				return nil, err
			}
			paths = append(paths, tmp...)
			continue
		}
		paths = append(paths, path)
	}
	return paths, nil
}

我們來(lái)測(cè)試一下:

package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"strings"
)

func main() {
	paths, _ := GetDirAllFilePaths("dir/")
	for _, path := range paths {
		fmt.Println(path)
	}
}

運(yùn)行輸出:

dir/bar.txt
dir/foo.txt
dir/subdir/baz.txt

哇,看起來(lái)大功告成。但果真如此嗎?

4.包含符號(hào)鏈接的情況

如果我們此時(shí)在目錄 dir 中加入一個(gè)符號(hào)鏈接,指向另外一個(gè)目錄,那結(jié)果會(huì)如何呢?

tree dir
dir
├── bar.txt
├── foo.txt
├── subdir
│   └── baz.txt
└── zipln -> ../zip

tree zip
zip
└── qux.txt

還是運(yùn)行調(diào)用 GetDirAllFilePaths(),我們得到的結(jié)果如下:

dir/bar.txt
dir/foo.txt
dir/subdir/baz.txt
dir/zipln

可見(jiàn),當(dāng)子目錄為符號(hào)鏈接時(shí),我們并沒(méi)有訪問(wèn)鏈接指向的目標(biāo)文件。

我們改變一下實(shí)現(xiàn),當(dāng)子目錄是符號(hào)鏈接時(shí),讀取目標(biāo)目錄下的文件。

// GetDirAllFilePathsFollowSymlink gets all the file paths in the specified directory recursively.
func GetDirAllFilePathsFollowSymlink(dirname string) ([]string, error) {
	// Remove the trailing path separator if dirname has.
	dirname = strings.TrimSuffix(dirname, string(os.PathSeparator))

	infos, err := ioutil.ReadDir(dirname)
	if err != nil {
		return nil, err
	}

	paths := make([]string, 0, len(infos))
	for _, info := range infos {
		path := dirname + string(os.PathSeparator) + info.Name()
		realInfo, err := os.Stat(path)
		if err != nil {
			return nil, err
		}
		if realInfo.IsDir() {
			tmp, err := GetDirAllFilePathFollowSymlink(path)
			if err != nil {
				return nil, err
			}
			paths = append(paths, tmp...)
			continue
		}
		paths = append(paths, path)
	}
	return paths, nil
}

我們來(lái)測(cè)試一下:

package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"strings"
)

func main() {
	paths, _ := GetDirAllFilePathsFollowSymlink("dir/")
	for _, path := range paths {
		fmt.Println(path)
	}
}

運(yùn)行輸出:

dir/bar.txt
dir/foo.txt
dir/subdir/baz.txt
dir/zipln/qux.txt

perfect,這就是我們想要的效果。

5.同時(shí)返回目錄的路徑

有時(shí),我們還需要目錄路徑,即獲取指定目錄下的文件和子目錄的路徑。比如在對(duì)一個(gè)目錄進(jìn)行壓縮時(shí)會(huì)需要。

還是以上文 dir 目錄為例,我們想要的結(jié)果是:

dir
dir/bar.txt
dir/foo.txt
dir/subdir
dir/subdir/baz.txt
dir/zipln
dir/zipln/qux.txt

我們只要稍微改造 GetDirAllFilePaths 和 GetDirAllFilePathsFollowSymlink 即可,在遍歷時(shí)把當(dāng)前的目錄加入結(jié)果集。

并更名 GetDirAllFilePaths 為 GetDirAllEntryPaths,GetDirAllFilePathsFollowSymlink 為 GetDirAllEntryPathsFollowSymlink,因?yàn)闂l目(Entry)比文件(File)語(yǔ)義更符合函數(shù)的功能,因?yàn)椴粌H可以獲取文件,也可以獲取目錄的路徑。

// GetDirAllEntryPaths gets all the file or dir paths in the specified directory recursively.
// Note that GetDirAllEntryPaths won't follow symlink if the subdir is a symbolic link.
func GetDirAllEntryPaths(dirname string, incl bool) ([]string, error) {
	// Remove the trailing path separator if dirname has.
	dirname = strings.TrimSuffix(dirname, string(os.PathSeparator))

	infos, err := ioutil.ReadDir(dirname)
	if err != nil {
		return nil, err
	}

	paths := make([]string, 0, len(infos))
	// Include current dir.
	if incl {
		paths = append(paths, dirname)
	}

	for _, info := range infos {
		path := dirname + string(os.PathSeparator) + info.Name()
		if info.IsDir() {
			tmp, err := GetDirAllEntryPaths(path, incl)
			if err != nil {
				return nil, err
			}
			paths = append(paths, tmp...)
			continue
		}
		paths = append(paths, path)
	}
	return paths, nil
}

// GetDirAllEntryPathsFollowSymlink gets all the file or dir paths in the specified directory recursively.
func GetDirAllEntryPathsFollowSymlink(dirname string, incl bool) ([]string, error) {
	// Remove the trailing path separator if dirname has.
	dirname = strings.TrimSuffix(dirname, string(os.PathSeparator))

	infos, err := ioutil.ReadDir(dirname)
	if err != nil {
		return nil, err
	}

	paths := make([]string, 0, len(infos))
	// Include current dir.
	if incl {
		paths = append(paths, dirname)
	}

	for _, info := range infos {
		path := dirname + string(os.PathSeparator) + info.Name()
		realInfo, err := os.Stat(path)
		if err != nil {
			return nil, err
		}
		if realInfo.IsDir() {
			tmp, err := GetDirAllEntryPathsFollowSymlink(path, incl)
			if err != nil {
				return nil, err
			}
			paths = append(paths, tmp...)
			continue
		}
		paths = append(paths, path)
	}
	return paths, nil
}

我們測(cè)試一下。

func main() {
	fmt.Println("not follow symlink:")
	paths, _ := GetDirAllEntryPaths("dir/", true)
	for _, path := range paths {
		fmt.Println(path)
	}

	fmt.Println("\nfollow symlink:")
	paths, _ = GetDirAllEntryPathsFollowSymlink("dir/", true)
	for _, path := range paths {
		fmt.Println(path)
	}
}

運(yùn)行輸出:

not follow symlink:
dir
dir/bar.txt
dir/foo.txt
dir/subdir
dir/subdir/baz.txt
dir/zipln

follow symlink:
dir
dir/bar.txt
dir/foo.txt
dir/subdir
dir/subdir/baz.txt
dir/zipln
dir/zipln/qux.txt

6.go-huge-util

以上函數(shù)已放置開(kāi)源庫(kù) go-huge-util,可 import 直接使用。

package main

import (
	"github.com/dablelv/go-huge-util/file"
)

func main() {
	// 獲取目錄下所有文件和子目錄名稱(chēng)(不會(huì)遞歸)。
	names, _ := file.ListDir("dir")

	// 遞歸獲取目錄下所有文件路徑(不解析符號(hào)鏈接)
	paths, _ := file.GetDirAllEntryPaths("dir", false)
	// 遞歸獲取目錄下所有文件和目錄路徑(不解析符號(hào)鏈接)
	paths, _ = file.GetDirAllEntryPaths("dir", true)

	// 遞歸獲取目錄下所有文件路徑(解析符號(hào)鏈接)
	paths, _ = file.GetDirAllEntryPathsFollowSymlink("dir", false)
	// 遞歸獲取目錄下所有文件與目錄路徑(解析符號(hào)鏈接)
	paths, _ = file.GetDirAllEntryPathsFollowSymlink("dir/", true)
}

歡迎大家 Star & PR。

參考文獻(xiàn)

io/ioutil - Go Packages

總結(jié)

到此這篇關(guān)于Golang遞歸獲取目錄下所有文件的文章就介紹到這了,更多相關(guān)Golang遞歸獲取目錄所有文件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Ruby序列化和持久化存儲(chǔ)(Marshal、Pstore)操作方法詳解

    Ruby序列化和持久化存儲(chǔ)(Marshal、Pstore)操作方法詳解

    這篇文章主要介紹了Ruby序列化和持久化存儲(chǔ)(Marshal、Pstore)操作方法詳解,包括Ruby Marshal序列化,Ruby Pstore存儲(chǔ),需要的朋友可以參考下
    2022-04-04
  • Golang?中反射的應(yīng)用實(shí)例詳解

    Golang?中反射的應(yīng)用實(shí)例詳解

    這篇文章主要為大家介紹了Golang?中反射的應(yīng)用實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • Go語(yǔ)言包和包管理詳解

    Go語(yǔ)言包和包管理詳解

    這篇文章主要為大家介紹了Go語(yǔ)言包和包管理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • Go語(yǔ)言學(xué)習(xí)之?dāng)?shù)組的用法詳解

    Go語(yǔ)言學(xué)習(xí)之?dāng)?shù)組的用法詳解

    數(shù)組是相同數(shù)據(jù)類(lèi)型的一組數(shù)據(jù)的集合,數(shù)組一旦定義長(zhǎng)度不能修改,數(shù)組可以通過(guò)下標(biāo)(或者叫索引)來(lái)訪問(wèn)元素。本文將通過(guò)示例詳細(xì)講解Go語(yǔ)言中數(shù)組的使用,需要的可以參考一下
    2022-04-04
  • Go語(yǔ)言狀態(tài)機(jī)的實(shí)現(xiàn)

    Go語(yǔ)言狀態(tài)機(jī)的實(shí)現(xiàn)

    本文主要介紹了Go語(yǔ)言狀態(tài)機(jī)的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-03-03
  • golang 之 wire 庫(kù)的使用小結(jié)

    golang 之 wire 庫(kù)的使用小結(jié)

    Wire是一個(gè)用于Go語(yǔ)言的編譯時(shí)依賴(lài)注入庫(kù),通過(guò)代碼生成提高性能和可維護(hù)性,它支持編譯時(shí)依賴(lài)注入、類(lèi)型安全、簡(jiǎn)單易用等功能,文章通過(guò)代碼示例展示了如何使用Wire進(jìn)行依賴(lài)注入,并探討了其優(yōu)點(diǎn)如解耦、可測(cè)試和維護(hù)性,感興趣的朋友跟隨小編一起看看吧
    2025-03-03
  • Go語(yǔ)言sync.Cond基本使用及原理示例詳解

    Go語(yǔ)言sync.Cond基本使用及原理示例詳解

    這篇文章主要為大家介紹了Go語(yǔ)言sync.Cond基本使用及原理示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-03-03
  • Go語(yǔ)言時(shí)間處理必備技巧全解析

    Go語(yǔ)言時(shí)間處理必備技巧全解析

    Golang 的時(shí)間處理是 Golang 編程中的一個(gè)重要方面,它涉及到了時(shí)間類(lèi)型、時(shí)間格式化、時(shí)間計(jì)算、時(shí)區(qū)處理以及定時(shí)器和超時(shí)機(jī)制等多個(gè)方面。在本文中,我們將從更深入的角度來(lái)探討 Golang 的時(shí)間處理
    2023-04-04
  • Go語(yǔ)言執(zhí)行系統(tǒng)命令行命令的方法

    Go語(yǔ)言執(zhí)行系統(tǒng)命令行命令的方法

    這篇文章主要介紹了Go語(yǔ)言執(zhí)行系統(tǒng)命令行命令的方法,實(shí)例分析了Go語(yǔ)言操作系統(tǒng)命令行的技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-02-02
  • go語(yǔ)言中http超時(shí)引發(fā)的事故解決

    go語(yǔ)言中http超時(shí)引發(fā)的事故解決

    我們使用的是golang標(biāo)準(zhǔn)庫(kù)的http client,對(duì)于一些http請(qǐng)求,我們?cè)谔幚淼臅r(shí)候,會(huì)考慮加上超時(shí)時(shí)間,如果超時(shí)可能會(huì)引起報(bào)錯(cuò),本文就記一次超時(shí)引發(fā)的事故
    2021-06-06

最新評(píng)論

抚宁县| 雷波县| 桐乡市| 固始县| 宁乡县| 潞城市| 湘乡市| 历史| 工布江达县| 翁牛特旗| 志丹县| 天气| 商丘市| 巴林右旗| 乐平市| 汤阴县| 兴海县| 银川市| 临城县| 保亭| 五寨县| 文安县| 金乡县| 务川| 娱乐| 上蔡县| 张掖市| 大厂| 禄劝| 新竹市| 平罗县| 原阳县| 顺昌县| 高密市| 定陶县| 台山市| 石河子市| 襄城县| 石家庄市| 遂溪县| 陕西省|