ضع قائمة بالملفات في مجلد باستخدام Go

أشرح في هذه المقالة كيفية الحصول على قائمة بالملفات داخل مجلد على نظام الملفات ، وهي مهمة تسمى أيضًاعبور الأشجارمع Go.

هناك نوعان من وظائف stdlib المفيدة التي يمكنك استخدامها وفقًا لهدفك.

أسرد 3 طرق: استخدامfilepath.Walkوioutil.ReadDirأوos.File.Readdir.

استخدامfilepath.Walk

الpath/filepathتوفر حزمة stdlib وظيفة المشي اليدوية. يقوم تلقائيًا بمسح الدلائل الفرعية ، لذا تأكد من أن هذا هو ما تريده بالفعل.

الاستخدام بسيط للغاية:

package main

import ( “fmt” “os” “path/filepath” )

func main() { var files []string

<span style="color:#a6e22e">root</span> <span style="color:#f92672">:=</span> <span style="color:#e6db74">"/some/folder/to/scan"</span>
<span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">filepath</span>.<span style="color:#a6e22e">Walk</span>(<span style="color:#a6e22e">root</span>, <span style="color:#66d9ef">func</span>(<span style="color:#a6e22e">path</span> <span style="color:#66d9ef">string</span>, <span style="color:#a6e22e">info</span> <span style="color:#a6e22e">os</span>.<span style="color:#a6e22e">FileInfo</span>, <span style="color:#a6e22e">err</span> <span style="color:#66d9ef">error</span>) <span style="color:#66d9ef">error</span> {
    <span style="color:#a6e22e">files</span> = append(<span style="color:#a6e22e">files</span>, <span style="color:#a6e22e">path</span>)
    <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">nil</span>
})
<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
    panic(<span style="color:#a6e22e">err</span>)
}
<span style="color:#66d9ef">for</span> <span style="color:#a6e22e">_</span>, <span style="color:#a6e22e">file</span> <span style="color:#f92672">:=</span> <span style="color:#66d9ef">range</span> <span style="color:#a6e22e">files</span> {
    <span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Println</span>(<span style="color:#a6e22e">file</span>)
}

}

filepath.Walkيقبل سلسلة تشير إلى المجلد الجذر ، وWalkFunc، نوع وظيفة مع التوقيع

type WalkFunc func(path string, info os.FileInfo, err error) error

يتم استدعاء هذه الوظيفة لكل تكرار لمسح المجلد.

الinfoمتغير من النوعos.FileInfoمهم لأنه يمكننا الحصول على العديد من المعلومات حول الملف الحالي: الاسم والحجم والوضع ووقت التعديل ، إذا كان مجلدًا أو ملفًا ، ومصدر البيانات الأساسي.

على سبيل المثال يمكننا تجنب معالجة المجلدات عن طريق إضافة

if info.IsDir() {
    return nil
}

يمكنك استبعاد (أو تضمين) الملفات إلى الشريحة بناءً على امتدادها ، باستخدامfilepath.Extوتمرير مسار الملف:

if filepath.Ext(path) == ".dat" {
    return nil
}

يمكننا تخزين اسم الملف بدلاً من استخدام مسار الملف

files = append(files, info.Name())

ويمكننا أيضًا تحديدWalkFuncبشكل منفصلإنهاء. نحتاج فقط إلى تمرير المؤشر إلىfilesفيvisit:

package main

import ( “fmt” “log” “os” “path/filepath” )

func visit(files []string) filepath.WalkFunc { return func(path string, info os.FileInfo, err error) error { if err != nil { log.Fatal(err) } files = append(*files, path) return nil } }

func main() { var files []string

<span style="color:#a6e22e">root</span> <span style="color:#f92672">:=</span> <span style="color:#e6db74">"/some/folder/to/scan"</span>
<span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">filepath</span>.<span style="color:#a6e22e">Walk</span>(<span style="color:#a6e22e">root</span>, <span style="color:#a6e22e">visit</span>(<span style="color:#f92672">&amp;</span><span style="color:#a6e22e">files</span>))
<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
    panic(<span style="color:#a6e22e">err</span>)
}
<span style="color:#66d9ef">for</span> <span style="color:#a6e22e">_</span>, <span style="color:#a6e22e">file</span> <span style="color:#f92672">:=</span> <span style="color:#66d9ef">range</span> <span style="color:#a6e22e">files</span> {
    <span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Println</span>(<span style="color:#a6e22e">file</span>)
}

}

استخدامioutil.ReadDir

filepath.Walkمفيد ولكنه يمسح المجلدات الفرعية أيضًا ، افتراضيًا ، والذي قد لا يكون ما تريده.

يوفر Go stdlib أيضًاioutil.ReadDir

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

يقرأ ReadDir الدليل المسمى باسم dirname ويعيد قائمة بإدخالات الدليل مرتبة حسب اسم الملف.

وهنا مثال من المستندات.ioutil.ReadDirيأخذ مسار المجلد كسلسلة ويعيد شريحة منos.FileInfoالتي وصفناها أعلاه.

package main

import ( “fmt” “io/ioutil” “log” )

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

<span style="color:#66d9ef">for</span> <span style="color:#a6e22e">_</span>, <span style="color:#a6e22e">file</span> <span style="color:#f92672">:=</span> <span style="color:#66d9ef">range</span> <span style="color:#a6e22e">files</span> {
    <span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Println</span>(<span style="color:#a6e22e">file</span>.<span style="color:#a6e22e">Name</span>())
}

}

استخدامos.File.Readdir

داخليا،ioutil.ReadDirيتم تنفيذ

// ReadDir reads the directory named by dirname and returns
// a list of directory entries sorted by filename.
func ReadDir(dirname string) ([]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
    }
    sort.Slice(list, func(i, j int) bool { return list[i].Name() < list[j].Name() })
    return list, nil
}

كما ترون يمسحdirnameويرتب الملفات بالاسم. إذا لم تكن بحاجة إلى الفرز ، يمكنك أيضًا استخدام

package main

import ( “fmt” “log” “os” )

func main() { dirname := “.”

<span style="color:#a6e22e">f</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">os</span>.<span style="color:#a6e22e">Open</span>(<span style="color:#a6e22e">dirname</span>)
<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
    <span style="color:#a6e22e">log</span>.<span style="color:#a6e22e">Fatal</span>(<span style="color:#a6e22e">err</span>)
}
<span style="color:#a6e22e">files</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">f</span>.<span style="color:#a6e22e">Readdir</span>(<span style="color:#f92672">-</span><span style="color:#ae81ff">1</span>)
<span style="color:#a6e22e">f</span>.<span style="color:#a6e22e">Close</span>()
<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
    <span style="color:#a6e22e">log</span>.<span style="color:#a6e22e">Fatal</span>(<span style="color:#a6e22e">err</span>)
}

<span style="color:#66d9ef">for</span> <span style="color:#a6e22e">_</span>, <span style="color:#a6e22e">file</span> <span style="color:#f92672">:=</span> <span style="color:#66d9ef">range</span> <span style="color:#a6e22e">files</span> {
    <span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Println</span>(<span style="color:#a6e22e">file</span>.<span style="color:#a6e22e">Name</span>())
}

}


المزيد من دروس Go: