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

使用Go開發(fā)一個文件同步小工具(附源碼)

 更新時間:2025年11月18日 09:51:19   作者:Mgx  
這篇文章主要為大家詳細介紹了如何使用Go開發(fā)一個文件同步小工具并附上源碼,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下

"你復(fù)制,我粘貼;你改了,我跟著動。" —— FileSync 的座右銘

大家好!今天我要給大家介紹一個我最近寫的小玩具——FileSync。它不是什么高大上的分布式同步系統(tǒng),也不是什么帶 GUI 界面的炫酷軟件,而是一個樸實無華、靠命令行吃飯、還帶點"佛系"氣質(zhì)的 Go 語言小工具。

它的任務(wù)很簡單:把 A 文件夾里的內(nèi)容,原封不動地同步到 B 文件夾里,并且自動跳過日志目錄(比如 \logs\、\log\、\runlog\),避免把一堆沒用的日志也搬過去占地方。

最重要的是——它還能優(yōu)雅退出!只要你在終端敲個 exit,它就會乖乖收工,不鬧脾氣 

它是怎么工作的

FileSync 的邏輯其實非常直白:

  • 啟動主線程:開始遍歷源目錄(fromDir)。
  • 智能過濾:遇到名字里帶 log 的文件夾?直接跳過!我們不關(guān)心日志,只關(guān)心"正經(jīng) 文件"。
  • 同步操作:
    • 如果是目錄 → 在目標位置創(chuàng)建同名目錄。
    • 如果是文件 → 比較修改時間!只有源文件比目標新(或目標不存在),才復(fù)制過去,并保留原始修改時間。
  • 每小時掃一次:干完一輪活,就去"打坐"一小時(其實是 sleep 3600秒),然后繼續(xù)巡邏。
  • 隨時聽令退出:主 goroutine 在后臺干活,主線程監(jiān)聽用戶輸入。一旦你說"exit",它立刻收手,等所有任務(wù)結(jié)束再退出,絕不拖泥帶水。

是不是有點像一個勤懇又聽話的數(shù)字園???

為什么說它"佛系"

  • 它不會瘋狂刷屏告訴你"我又復(fù)制了一個文件!"(雖然現(xiàn)在會打印路徑,但你可以輕松注釋掉)。
  • 它不爭不搶,每小時才工作一次,其余時間都在"冥想"。
  • 它尊重文件的"前世今生"——連修改時間都要原樣保留,生怕打擾了文件的情緒。
  • 你說"走",它絕不賴著不走,還會禮貌地說一句:"FileSync soft exit"。

這哪是程序?分明是個修行千年的老和尚寫的代碼 

使用須知(別踩坑)

必須傳兩個參數(shù):./FileSync /path/to/source /path/to/target

路徑分隔符注意:代碼里用了 \\ 來判斷 Windows 風格的日志路徑。如果你在 Linux/macOS 上跑,可能需要改成 /logs/。不過 filepath.Walk 是跨平臺的,所以實際運行沒問題,只是過濾邏輯可能失效(因為 Linux 路徑不含反斜杠)。建議改成 / 或使用 filepath.Separator 更健壯。

權(quán)限問題:確保程序有讀源目錄、寫目標目錄的權(quán)限。

大文件警告:目前是全量復(fù)制,沒做增量或斷點續(xù)傳,超大文件可能會卡一下。

改進建議(留給未來的你)

用 fsnotify 監(jiān)聽文件變化,實時同步,告別"每小時打坐"。

支持配置文件,自定義忽略規(guī)則。

加日志輸出開關(guān),別總往 stdout 打。

支持雙向同步 or 增量備份模式。

給它起個更酷的名字,比如 ZenSync?

源碼奉上

下面就是這個"佛系同步器"的完整源碼,Go 語言編寫,簡潔明了,歡迎拿去魔改!

package main

import (
	"fmt"
	"io"
	"os"
	"path/filepath"
	"strings"
	"sync"
	"time"
)

var exit = false           // 退出狀態(tài)控制
var wg sync.WaitGroup      // 保證正常退出

func main() {
	fmt.Println("FileSync soft run")
	if len(os.Args) < 3 {
		fmt.Println("Usage: FileSync <source_dir> <target_dir>")
		return
	}
	fromDir := os.Args[1]
	toDir := os.Args[2]
	wg.Add(1)
	go mainRun(fromDir, toDir) // 啟動工作主線程

	for {
		var cmd string
		fmt.Scanln(&cmd)
		fmt.Println("cmd:", cmd)
		if cmd == "exit" {
			exit = true
			break
		} else {
			fmt.Println("unknow command")
			fmt.Println("exit exit soft")
		}
	}
	wg.Wait()
	fmt.Println("FileSync soft exit")
}

func mainRun(fromDir, toDir string) {
	defer wg.Done()
	for !exit {
		filepath.Walk(fromDir, func(path string, info os.FileInfo, err error) error {
			if err != nil {
				return nil
			}
			fmt.Println(path)
			p := strings.ToLower(path)
			// 跳過常見日志目錄(注意:Windows風格路徑)
			if strings.Contains(p, "\\runlog\\") || 
			   strings.Contains(p, "\\logs\\") || 
			   strings.Contains(p, "\\log\\") {
				return nil
			}
			if info.IsDir() {
				syncDir(strings.Replace(path, fromDir, toDir, 1))
			} else {
				syncFile(path, strings.Replace(path, fromDir, toDir, 1))
			}
			return nil
		})
		// 每小時同步一次
		for i := 0; i < 60*60; i++ {
			time.Sleep(time.Second)
			if exit {
				break
			}
		}
	}
}

func syncDir(dirname string) {
	if err := os.MkdirAll(dirname, 0777); err != nil {
		fmt.Println(err)
	}
}

func syncFile(f, t string) {
	CopyFile(f, t)
}

func CopyFile(f, t string) (written int64, err error) {
	src, err := os.Open(f)
	if err != nil {
		return
	}
	defer src.Close()
	st, _ := src.Stat()
	mt := st.ModTime()

	var dst *os.File
	if ft, exist := checkFileIsExist(t); exist {
		// 修改時間相同,跳過復(fù)制
		if st.ModTime().UnixNano() == ft.UnixNano() {
			fmt.Println("修改時間相同,放棄")
			return
		}
		dst, err = os.OpenFile(t, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0777)
		if err != nil {
			fmt.Println(err)
			return
		}
	} else {
		dst, err = os.Create(t)
		if err != nil {
			fmt.Println(err)
			return
		}
	}
	l, err := io.Copy(dst, src)
	dst.Close()
	if err == nil {
		// 保留原始修改時間
		err := os.Chtimes(t, mt, mt)
		if err != nil {
			fmt.Println(err)
		}
	}
	return l, err
}

func checkFileIsExist(filename string) (time.Time, bool) {
	fi, err := os.Stat(filename)
	if os.IsNotExist(err) {
		return time.Now(), false
	} else if err != nil {
		return time.Now(), false
	}
	return fi.ModTime(), true
}

結(jié)語

雖然這個小工具簡單,但它體現(xiàn)了 Go 語言的并發(fā)之美(一個 goroutine 干活,主線程監(jiān)聽退出)、文件操作的便捷性,以及——一點點程序員的幽默感。

下次當你需要一個輕量、可控、不吵不鬧的同步腳本時,不妨試試這個"佛系 FileSync"。說不定,它還能幫你悟出點編程禪意呢 

代碼已開源,心法自悟。

P.S. 如果你在 macOS/Linux 上使用,請記得把 \\log\\ 這類判斷改成 /log/,或者更優(yōu)雅地用 filepath.Join("log") 來處理路徑分隔符哦!

到此這篇關(guān)于使用Go開發(fā)一個文件同步小工具(附源碼)的文章就介紹到這了,更多相關(guān)Go文件同步內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Go實現(xiàn)map并發(fā)安全的3種方式總結(jié)

    Go實現(xiàn)map并發(fā)安全的3種方式總結(jié)

    Go的原生map不是并發(fā)安全的,在多協(xié)程讀寫同一個map的時候,安全性無法得到保障,這篇文章主要給大家總結(jié)介紹了關(guān)于Go實現(xiàn)map并發(fā)安全的3種方式,需要的朋友可以參考下
    2023-10-10
  • 使用Golang簡單實現(xiàn)七牛圖片處理API

    使用Golang簡單實現(xiàn)七牛圖片處理API

    本文給大家實現(xiàn)的是使用Golang簡單實現(xiàn)七牛圖片處理API的方法和步驟,基于PIPE庫實現(xiàn)的,非常的實用,有需要的小伙伴可以參考下
    2016-08-08
  • 簡單聊一聊Go語言中的數(shù)組和切片

    簡單聊一聊Go語言中的數(shù)組和切片

    數(shù)組和切片由于語法十分相似,在使用中容易混淆,要認真區(qū)分,下面這篇文章主要給大家介紹了關(guān)于Go語言中數(shù)組和切片的相關(guān)資料,需要的朋友可以參考下
    2021-07-07
  • go sync.Map基本原理深入解析

    go sync.Map基本原理深入解析

    這篇文章主要為大家介紹了go sync.Map基本原理深入解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-01-01
  • Golang 限流器的使用和實現(xiàn)示例

    Golang 限流器的使用和實現(xiàn)示例

    這篇文章主要介紹了Golang 限流器的使用和實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-06-06
  • 基于Go語言開發(fā)篇一個命令行進程監(jiān)控工具

    基于Go語言開發(fā)篇一個命令行進程監(jiān)控工具

    在生產(chǎn)和開發(fā)環(huán)境中,監(jiān)控關(guān)鍵進程的存活與資源使用是非常常見的需求,本篇將開發(fā)一個輕量級的命令行進程監(jiān)控工具,感興趣的小伙伴可以了解下
    2025-09-09
  • golang中strconv.ParseInt函數(shù)用法示例

    golang中strconv.ParseInt函數(shù)用法示例

    這篇文章主要介紹了golang中strconv.ParseInt函數(shù)用法,實例分析了strconv.ParseInt函數(shù)將字符串轉(zhuǎn)換為數(shù)字的簡單使用方法,需要的朋友可以參考下
    2016-07-07
  • Go中l(wèi)og包異或組合配置妙用詳解

    Go中l(wèi)og包異或組合配置妙用詳解

    在 Go 語言的 log 包中,使用“位運算相或” (|) 來配置日志的 flag,可以讓我們靈活地組合多種日志信息輸出選項,下面我們就來看看這種方法的好處和原理吧
    2024-11-11
  • Go語言字符串高效拼接的實現(xiàn)

    Go語言字符串高效拼接的實現(xiàn)

    這篇文章主要介紹了Go語言字符串高效拼接的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-02-02
  • Go創(chuàng)建一個包并使用(導(dǎo)入本地包和注意事項)

    Go創(chuàng)建一個包并使用(導(dǎo)入本地包和注意事項)

    有時候需要自己寫一個包方便多次使用,但是在導(dǎo)入自己寫的包時遇到了問題,本文主要介紹了Go創(chuàng)建一個包并使用(導(dǎo)入本地包和注意事項),感興趣的可以了解一下
    2023-11-11

最新評論

东平县| 青铜峡市| 鄂州市| 榕江县| 长海县| 古田县| 宁陵县| 京山县| 芜湖市| 宜都市| 汝城县| 韶关市| 绥滨县| 伊吾县| 永胜县| 施秉县| 三穗县| 新余市| 榆树市| 舞钢市| 田东县| 齐河县| 韶山市| 铁岭县| 中宁县| 黄平县| 集贤县| 当雄县| 东明县| 娄烦县| 富民县| 潢川县| 平谷区| 镇平县| 东乌| 阆中市| 郸城县| 华池县| 定南县| 西充县| 湟源县|