首頁 >後端開發 >Golang >整理您的桌面:在 Go 中建立文件管理器。

整理您的桌面:在 Go 中建立文件管理器。

Mary-Kate Olsen
Mary-Kate Olsen原創
2024-12-05 03:06:14533瀏覽

你的桌面混亂嗎?您的桌面或下載目錄中是否有各種各樣的檔案?讓我們用一個簡單的腳本來解決這個問題。

正如我們在任何 go 專案開始時所做的那樣,我們使用「go mod init」指令來產生 go.mod 檔案。為了簡單起見,我們將在 main.go 檔案中編寫所有邏輯。

在編寫任何程式碼之前,讓我們先討論一下我們希望腳本如何表現。我們希望能夠將文件組織到指示文件類型或建立日期的目錄中。簡而言之,我們希望我們的腳本將視訊檔案分類到視訊目錄中,將音樂檔案分類到音樂目錄中,依此類推;或將在特定日期建立的所有檔案排序到同一目錄中。

現在讓我們來編碼:

建立一個main.go檔案並寫入以下內容:

package main

type fileAnalyzer interface {
    analyzeAndSort() error
}

func analyze(fa fileAnalyzer) error {
    return fa.analyzeAndSort()
}

因為我們希望程式按照不同的標準對檔案進行排序,所以我們建立了一個 fileAnalyzer 接口,它定義了一個方法:analyzeAndSort。
然後我們編寫一個函數:analyze - 它將任何實作 fileAnalyzer 介面的結構作為參數並執行它的analyzeAndSort 方法。

在某些情況下,就像我們將在此程式中看到的那樣,可能存在您不想移動的某些檔案。例如,在測試腳本時,我們不希望程式將我們的 go 檔案或執行檔/二進位檔案移到另一個目錄中。為了防止這種情況發生,我們必須建立一個黑名單,其中包括我們希望保持不變的所有文件。

在我們的 main.go 檔案中,寫入以下內容:

var blacklist = []string{
    "go",
    "mod",
    "exe",
    "ps1",
}

在這裡,我新增了我希望保持未排序的檔案的檔案副檔名。 “.go”和“.mod”是 go 檔案的副檔名。因為我使用 Windows 機器,所以我的二進位檔案將以「.exe」作為副檔名。我還包含了“.ps1”,因為我喜歡在開發中使用 powershell 腳本 - 正如您將看到的。

接下來,我們寫一些輔助函數。

func getFileExtension(name string) string {
    return strings.TrimPrefix(filepath.Ext(name), ".")
}

func listFiles(dirname string) ([]string, error) {
    var files []string

    list, err := os.ReadDir(dirname)
    if err != nil {
        return nil, err
    }

    for _, file := range list {
        if !file.IsDir() {
            files = append(files, file.Name())
        }
    }

    return files, nil
}

func listDirs(dirname string) ([]string, error) {
    var dirs []string

    list, err := os.ReadDir(dirname)
    if err != nil {
        return nil, err
    }

    for _, file := range list {
        if file.IsDir() {
            dirs = append(dirs, file.Name())
        }
    }

    return dirs, nil
}

func mkdir(dirname string) error {
    err := os.Mkdir(dirname, 0644)

    if err != nil && os.IsExist(err) {
        return nil
    }

    var e *os.PathError

    if err != nil && errors.As(err, &e) {
        return nil
    }

    return err
}

func moveFile(name string, dst string) error {
    return os.Rename(name, filepath.Join(dst, name))
}

func getCurrentDate(t time.Time) string {
    return t.Format("2006-01-02")
}

func filter[T any](ts []T, fn func(T) bool) []T {
    filtered := make([]T, 0)

    for i := range ts {
        if fn(ts[i]) {
            filtered = append(filtered, ts[i])
        }
    }

    return filtered
}

其中大部分都是不言自明的,但我想談談「mkdir」函數。 “mkdir”函數建立一個目錄,並將名稱作為參數傳遞給它 - 但如果該目錄已存在或存在“os.PathError”,該函數不會傳回錯誤。

現在讓我們建立一個實作 fileAnalyzer 介面的結構體:

package main

type fileAnalyzer interface {
    analyzeAndSort() error
}

func analyze(fa fileAnalyzer) error {
    return fa.analyzeAndSort()
}

fileTypeAnalyzer 結構有兩個屬性:wd,它保存目前工作目錄的名稱和映射器。映射器的鍵將是偵測到的檔案類型,而其值是與該鍵關聯的檔案副檔名清單。然後,我們建立一個建構函數並向映射器提供文件類型及其關聯文件副檔名。請隨意在清單中新增更多檔案類型和副檔名。 anaylyzeAndSort 方法呼叫幾個輔助函數和方法,將檔案副檔名對應到檔案類型,建立檔案類型目錄並將檔案移到所述目錄中。我還添加了一個“misc”資料夾來保存映射器未捕獲的檔案 - 當然不包括列入黑名單的檔案。

我們也希望能夠按建立日期組織文件。讓我們建立另一個實作 fileAnalyzer 介面但按日期組織文件的結構。

var blacklist = []string{
    "go",
    "mod",
    "exe",
    "ps1",
}

許多邏輯與 fileTypeAnalyzer 的邏輯相同。主要區別是我們不提供映射器 - 相反,我們從文件資訊中獲取創建日期並相應地創建目錄。

現在讓我們將所有內容放在我們的主函數中:

func getFileExtension(name string) string {
    return strings.TrimPrefix(filepath.Ext(name), ".")
}

func listFiles(dirname string) ([]string, error) {
    var files []string

    list, err := os.ReadDir(dirname)
    if err != nil {
        return nil, err
    }

    for _, file := range list {
        if !file.IsDir() {
            files = append(files, file.Name())
        }
    }

    return files, nil
}

func listDirs(dirname string) ([]string, error) {
    var dirs []string

    list, err := os.ReadDir(dirname)
    if err != nil {
        return nil, err
    }

    for _, file := range list {
        if file.IsDir() {
            dirs = append(dirs, file.Name())
        }
    }

    return dirs, nil
}

func mkdir(dirname string) error {
    err := os.Mkdir(dirname, 0644)

    if err != nil && os.IsExist(err) {
        return nil
    }

    var e *os.PathError

    if err != nil && errors.As(err, &e) {
        return nil
    }

    return err
}

func moveFile(name string, dst string) error {
    return os.Rename(name, filepath.Join(dst, name))
}

func getCurrentDate(t time.Time) string {
    return t.Format("2006-01-02")
}

func filter[T any](ts []T, fn func(T) bool) []T {
    filtered := make([]T, 0)

    for i := range ts {
        if fn(ts[i]) {
            filtered = append(filtered, ts[i])
        }
    }

    return filtered
}

我們設定一個記錄器;取得目前工作目錄作為參數傳遞給我們的 fileAnalyzer 實作;建立一個模式變數來保存作為標誌傳遞給應用程式的值,並建立一個 switch 語句來控制我們想要如何排序。最後我們呼叫分析函數並將我們的 fileAnalyzer 實作作為參數傳遞。

僅此而已。讓我們建立二進位檔案並進行測試。我打電話給我的分類員。你可以用「go build -o [name]」來稱呼你的任何你想要的名字

這是一個散佈著不同類型檔案的資料夾:

Organize your desktop: Build a file organizer in Go.

讓我們按文件類型組織:

Organize your desktop: Build a file organizer in Go.

Organize your desktop: Build a file organizer in Go.

讓我們按文件建立日期進行組織:

Organize your desktop: Build a file organizer in Go.

Organize your desktop: Build a file organizer in Go.

作為獎勵,如果您使用 Windows 電腦並且使用 powershell - 這裡有一個腳本可以幫助您順利測試您的程式。

建立一個task.ps1 檔案並輸入以下內容:

type fileTypeAnalyzer struct {
    wd     string
    mapper map[string][]string
}

func newFileTypeAnalyzer(wd string) *fileTypeAnalyzer {
    return &fileTypeAnalyzer{
        wd: wd,
        mapper: map[string][]string{
            "video":  {"mp4", "mkv", "3gp", "wmv", "flv", "avi", "mpeg", "webm"},
            "music":  {"mp3", "aac", "wav", "flac"},
            "images": {"jpg", "jpeg", "png", "gif", "svg", "tiff"},
            "docs":   {"docx", "csv", "txt", "xlsx"},
            "books":  {"pdf", "epub"},
        },
    }
}

func (f fileTypeAnalyzer) analyzeAndSort() error {
    files, err := listFiles(f.wd)
    if err != nil {
        return fmt.Errorf("could not list files: %w", err)
    }

    if err := f.createFileTypeDirs(files...); err != nil {
        return err
    }

    return f.moveFileToTypeDir(files...)
}

func (f fileTypeAnalyzer) moveFileToTypeDir(files ...string) error {
    dirs, err := listDirs(f.wd)
    if err != nil {
        return fmt.Errorf("could not list directories: %w", err)
    }

    for _, dir := range dirs {
        for _, file := range files {
            if slices.Contains(f.mapper[dir], strings.ToLower(getFileExtension(file))) {
                if err := moveFile(file, dir); err != nil {
                    return err
                }
            }
        }
    }

    files, err = listFiles(f.wd)
    if err != nil {
        return err
    }

    if len(files) == 0 {
        return nil
    }

    files = filter(files, func(f string) bool {
        return !slices.Contains(blacklist, getFileExtension(f))
    })

    for i := range files {
        if err := f.moveToMisc(files[i]); err != nil {
            return err
        }
    }

    return nil
}

func (f fileTypeAnalyzer) moveToMisc(file string) error {
    if err := mkdir("misc"); err != nil {
        return err
    }

    return moveFile(file, "misc")
}

func (f fileTypeAnalyzer) createFileTypeDirs(files ...string) error {
    for ftype, fvalues := range f.mapper {
        for _, file := range files {
            if slices.Contains(fvalues, getFileExtension(file)) {
                if err := mkdir(ftype); err != nil {
                    return fmt.Errorf("could not create folder: %w", err)
                }
            }
        }
    }

    return nil
}

使用腳本建立二進位檔案:

Organize your desktop: Build a file organizer in Go.

使用腳本取消組織文件:

Organize your desktop: Build a file organizer in Go.

使用腳本刪除目錄:

Organize your desktop: Build a file organizer in Go.

以上是整理您的桌面:在 Go 中建立文件管理器。的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn