首頁  >  文章  >  後端開發  >  在 GO 整理您的下載

在 GO 整理您的下載

Linda Hamilton
Linda Hamilton原創
2024-10-31 05:44:30966瀏覽

Organizador de seus downloads em GO

大家好,離子又來了。

害怕學習人工智慧有一天會完成的事情讓我感到非常痛苦。但是,如果「解決問題」仍然是對未來人類的要求,為什麼不堅持呢?

這次我又帶來了一個教學。比第一個沒啥用。那我們來定義一下「問題」的結構,因為我們已經知道一件事:那些沒有問題的人,是因為他們看起來不夠。對於那些還沒有找到它們的人來說,創建它們只是時間問題。

專案結構

程式最簡單的結構是:

  • 掃描資料夾(例如下載資料夾或其他目錄)
  • 辨識相關目錄中每個檔案的類型
  • 將檔案移到與其類型對應的子資料夾(影像、影片、文件...)

啟動專案

建立目錄並導航到它:

mkdir organizador
cd organizador

建立一個 Organizer.go 檔案並啟動其模組:

touch organizador.go
go mod init organizador.go

你應該有或多或少像這樣的東西:

~/organizador
.
├── go.mod
└── organizador.go

第 1 部分:檢查目錄是否存在

讓我們定義來源目錄dirOrigem,我們將在其中執行組織。定義後,我們檢查它是否確實存在,否則我們將回傳錯誤:

package main

import (
    "fmt"
    "os"
)

// Defina o deretório o qual você quer organizar como variável global
var dirOrigem string := "/Users/User/Downloads" // Troque o diretório 

func main() {

    // Verificar se o diretório existe, caso contrário, retornar erro
    if _, err := os.Stat(dirOrigem); os.IsNotExist(err) {
        fmt.Println("BAD DIR :( \nDiretório não encontrado: ", dirOrigem)
        return
    } else {
        // Imprimir mensagem caso o diretório exista
        fmt.Println("GOOD DIR :) \nDiretório encontrado: ", dirOrigem)
    }
}

現在,讓我們對上面的程式碼做一些考慮:

  • os.Stat函數傳回兩個類型為os.FileInfo和錯誤err的值。
  1. FileInfo 是一個傳回詳細文件資訊的接口,在本例中我們不需要。因此,為了忽略這個接口,我們使用_,。但是,我們不想忽略錯誤: if _, err := ...
  2. 我們將錯誤err 作為參數傳遞給os.IsNotExist() 函數,因為如果目錄不存在,os.Stat() 函數將傳回NOT NULL 錯誤,從而導致os.IsNotExist() 傳回true,執行我們的訊息:BAD DIR :(
  3. 如果 os.IsNotExist() 傳回 false,我們將從 else 條件列印訊息:GOOD DIR :)

第 2 部分:回呼函數概念太瘋狂了,老兄!

你有沒有註意到,我們在這裡一點一點地享受機械式鍵盤聲音的比特和位元組。 _查卡查卡繁榮! _

現在我們要建立一個回呼函數。這是我從未真正了解過的東西,或者從來沒有足夠的好奇心去質疑我是否在前 golang 生活中的任何 Python 程式碼中使用過這個概念。

回呼函數是一個帶有參數傳遞給另一個函數的函數。

如果您已經熟悉這個概念,那麼恭喜您,否則,恭喜您。換句話說,恭喜你!

現在讓我們建立一個 filepath.Walk 回呼函數,它將作為參數傳遞給另一個函數。

mkdir organizador
cd organizador
touch organizador.go
go mod init organizador.go

但是等等,filepath.Walk 是如何呼叫回呼函數的呢?

當您呼叫 filepath.Walk(sourcedir, listFiles) 時,filepath.Walk 函數會執行遍歷 sourcedir 中的所有檔案和子目錄的繁重工作。

對於找到的每個檔案或目錄,它都會使用三個參數來呼叫 listFiles 函數:

  • path:目前檔案或目錄的完整路徑。
  • info:一個 os.FileInfo 對象,包含檔案/目錄的資訊(例如名稱、是否為目錄、大小等)。
  • err:如果存取此檔案或目錄時出現問題,則會出現錯誤。

Go 自動理解 listFiles 必須接收這三個參數,因為 filepath.Walk 期望一個完全遵循此簽章的函數:

~/organizador
.
├── go.mod
└── organizador.go

請注意,Walk 函數回傳一個錯誤!這是相關的!

這就是為什麼我們將函數 filepath.Walk(dirOrigem,listarArquivos) 等同於錯誤:

package main

import (
    "fmt"
    "os"
)

// Defina o deretório o qual você quer organizar como variável global
var dirOrigem string := "/Users/User/Downloads" // Troque o diretório 

func main() {

    // Verificar se o diretório existe, caso contrário, retornar erro
    if _, err := os.Stat(dirOrigem); os.IsNotExist(err) {
        fmt.Println("BAD DIR :( \nDiretório não encontrado: ", dirOrigem)
        return
    } else {
        // Imprimir mensagem caso o diretório exista
        fmt.Println("GOOD DIR :) \nDiretório encontrado: ", dirOrigem)
    }
}

畢竟,因為它回傳一個錯誤,所以它是一個錯誤XD

實際例子

以下更詳細地介紹了每一步發生的情況:

func main() { 
// Restante do código
.
.
.

// Percorrer e listar os arquivos no diretório dirOrigem
    err := filepath.Walk(dirOrigem, listarArquivos)
    if err != nil {
        fmt.Println("Erro ao percorrer o diretório: ", err)
    }
}

對於 dirOrigem 中的每個檔案或目錄,filepath.Walk 將呼叫 listFiles,就好像它是這樣的:

// Função que lista os arquivos do diretório
func listarArquivos(caminho string, info os.FileInfo, err error) error {
    if err != nil {
        return err
    }

    // Ignorar diretórios e exibir apenas arquivos
    if !info.IsDir() && !strings.HasPrefix(info.Name(), ".") {
        fmt.Println("Arquivo encontrado: ", info.Name())
    }
    return nil
}

在此範例中,對於每個呼叫:

  • path:接收檔案或目錄的路徑。
  • 資訊:包含有關此項目的資訊(例如名稱和類型)。
  • err:用於捕獲存取檔案/目錄時的任何特定錯誤。

回呼函數

listFiles 是 filepath.Walk 使用這些值自動呼叫的回呼函數。這樣,我們就不需要擔心設定path、info和err值; filepath.Walk 已經為我們做到了這一點。

PHE!

現在在你的終端上進行頑皮的測試:

// Função Walk()
func Walk(root string, walkFn WalkFunc) error

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

你可以得到結果:

err := filepath.Walk(dirOrgiem, listarArquivos)

或:

//Percorrer e listar os arquivos no diretório
err := filepath.Walk(dirOrigem, listarArquivos)

在這種情況下,我只是在“下載”中添加了一個額外的“s”,這樣原始目錄就會不正確。

現在刪除 listFiles 函數,因為我們不會使用它。

開個玩笑,我們只是要更改她的名字並添加其他邏輯。

第 3 部分:組織! =組織

組織得很好,組織得很好。

在我的精彩觀察之後,讓我們繼續我們真正感興趣的部分:組織整個事情。

人生的一個諷刺是,在整理文件之前,我們必須先整理一下下一步的想法。

我們的下一個功能基本上需要:

  • 根據 dirOrigem 目錄中每個檔案的副檔名建立子資料夾(如果不存在)。
  • 根據副檔名將檔案移到各自的資料夾中。
  • 但是如果檔案已經在組織子資料夾中,則不應再次建立它們。

讓我們來了解這段程式碼的每個部分的作用:

mkdir organizador
cd organizador

組織文件函數的結構

為目錄結構中找到的每個檔案或資料夾呼叫organizeFiles函數。它檢查根據副檔名組織每個檔案的條件,建立子資料夾並在必要時移動檔案。

touch organizador.go
go mod init organizador.go

這裡,organizeFiles 函數採用三個參數:

  • path:目前檔案或目錄的完整路徑。
  • info:文件或目錄信息,從類型 os.FileInfo.
  • 獲取
  • err:嘗試存取專案時可能發生的錯誤。

先檢查存取檔案/目錄時是否出現錯誤。如果是,則立即返回。

過濾檔案並忽略隱藏目錄

~/organizador
.
├── go.mod
└── organizador.go

此片段進行兩項檢查:

  • !info.IsDir():檢查該項目是否不是目錄(即,它是檔案)。
  • !strings.HasPrefix(info.Name(), "."):檢查檔案名稱是否不以「.」開頭,忽略基於 Unix 的系統上的隱藏檔案。

如果滿足兩個條件,則檔案將顯示為 fmt.Println。

識別檔案副檔名並建立子資料夾名稱

package main

import (
    "fmt"
    "os"
)

// Defina o deretório o qual você quer organizar como variável global
var dirOrigem string := "/Users/User/Downloads" // Troque o diretório 

func main() {

    // Verificar se o diretório existe, caso contrário, retornar erro
    if _, err := os.Stat(dirOrigem); os.IsNotExist(err) {
        fmt.Println("BAD DIR :( \nDiretório não encontrado: ", dirOrigem)
        return
    } else {
        // Imprimir mensagem caso o diretório exista
        fmt.Println("GOOD DIR :) \nDiretório encontrado: ", dirOrigem)
    }
}

這裡:

  • strings.ToLower(filepath.Ext(info.Name())):提取檔案副檔名(例如.txt)並將其轉換為小寫以確保一致性。
  • subfolder := filepath.Join(sourcedir, extension[1:]):建立檔案將移至的子資料夾的完整路徑。副檔名[1:]去掉副檔名中的起始點(.),形成子資料夾的名稱,如txt。

如果子資料夾尚不存在,則建立它

func main() { 
// Restante do código
.
.
.

// Percorrer e listar os arquivos no diretório dirOrigem
    err := filepath.Walk(dirOrigem, listarArquivos)
    if err != nil {
        fmt.Println("Erro ao percorrer o diretório: ", err)
    }
}

這裡,函數:

  • 使用 os.Stat 檢查子資料夾是否已存在。
  • 如果子資料夾不存在 (os.IsNotExist(err)),則使用 os.Mkdir(subfolder, os.ModePerm) 建立它。
  • os.ModePerm 設定新資料夾的預設權限。如果建立資料夾時出錯,則會顯示並返回。

設定檔案目標路徑

mkdir organizador
cd organizador

此時,destinationPath 代表檔案將被移動的最終路徑。它是使用 filepath.Join 建構的,用於將子資料夾路徑連接到檔案名稱。

檢查檔案是否已位於目標資料夾中

touch organizador.go
go mod init organizador.go
  • 此程式碼片段將目標路徑與目前檔案路徑進行比較。如果它們相同,則表示該檔案已位於正確的子資料夾中,因此會被忽略並顯示一則訊息 (fmt.Printf)。
  • 否則,os.Rename(path, destinationPath) 會將檔案移到子資料夾。如果移動過程中出現錯誤,則傳回。

最終總結

功能:

  1. 捲動目錄,檢查每個項目。
  2. 忽略隱藏的目錄和檔案。
  3. 確定檔案副檔名以及目標子資料夾。
  4. 建立子資料夾(如果尚不存在)。
  5. 將檔案移至子資料夾,除非該檔案已存在。

使用 filepath.Walk(dirOrigem, OrganizeFiles) 將此函數傳遞給目錄中的每個文件,使它們全部自動組織。

這段程式碼非常適合作為文件組織函數,因為它在單一函數中處理創建和移動邏輯 - 一種高效且有組織的結構形式。

回購:https://github.com/ionnss/organizador


***地球上的另一天,
離子

以上是在 GO 整理您的下載的詳細內容。更多資訊請關注PHP中文網其他相關文章!

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