精华内容
下载资源
问答
  • 文件夹md5计算工具

    2020-03-10 14:24:36
    计算文件夹唯一标识,类似md5,可用于判断文件夹是否相同 文件夹名,文件名,目录结构,文件内容统统参与计算,根目录文件夹名不会参与计算。
  • 网上找了好多资料关于CheckSum...没办法自己写一个,一个文件夹对应一个MD5值,也就是将所有文件排序,再将文件流整合到一起,计算MD5值。 工具界面友好,使用方便,只要将需要计算文件夹拖到工具上,点击计算即可。
  • 1、windows下计算文件夹下所有文件的MD5值,并保存在指定文件 2、非递归方式扫描文件夹下所有文件。 3、压缩包中包含源代码
  • 案例需求:我们的监测系统会...1. 单一文件的md5计算我们首先将需求任务进行分解,既然需要计算文件夹下的所有文件md5值,我们必须先考虑如何实现单一文件的md5值计算。下面就是一个简单的md5求值程序,这里我们通过...

    案例需求:我们的监测系统会定期的检查配置文件的变动,这些配置文件放置在一个独立的文件夹下面,我们可以通过对于整个的文件夹内所有文件进行md5的计算来完成监测,本文就通过Go语言实现了一个命令行工具,完成上述的需求。

    1. 单一文件的md5计算

    我们首先将需求任务进行分解,既然需要计算文件夹下的所有文件md5值,我们必须先考虑如何实现单一文件的md5值计算。

    下面就是一个简单的md5求值程序,这里我们通过参数传递进去需要计算的文件,然后调用go语言提供的内置的crypto包中的函数来完成取值,计算得出的结果使用16进制的方式打印出来。

    package main

    import (

    "crypto/md5"

    "fmt"

    "io/ioutil"

    "os"

    )

    func Md5SumFile(file string) (value [md5.Size]byte, err error) {

    data, err := ioutil.ReadFile(file)

    if err != nil {

    return

    }

    value = md5.Sum(data)

    return

    }

    func main() {

    if len(os.Args) <2 {

    fmt.Println("Usage: ./md5file yourfile")

    return

    }

    md5Value, err := Md5SumFile(os.Args[1])

    if err != nil {

    fmt.Println(err.Error())

    return

    }

    fmt.Printf("%x %s\n", md5Value, os.Args[1])

    }

    执行程序输出如下面所示:

    $ go run src/md5_files.go src/test.txt

    fc3ff98e8c6a0d3087d515c0473f8677 src/test.txt

    2 文件的遍历与计算

    2.1 参数处理

    如果我们传递进去的是一个文件夹则如何处理呢?这里我们先通过改造原始的程序使得程序可以接收不同的参数类型比如-d代表了后面的为一个目录文件,-f代表了传递的是一个文件,这里我们需要借助于golang的flags包来完成参数的解析,解析完毕后我们就可以按照对应的方式处理参数了。

    var directory, file *string

    func init() {

    directory = flag.String("d", "", "The directory contains all the files that need to calculate the md5 value")

    file = flag.String("f", "", "The file that need to caclulate the md5 value")

    }

    func main() {

    flag.Parse()

    if *directory == "" && *file == "" {

    flag.Usage()

    return

    }

    if *file != "" {

    md5Value, err := Md5SumFile(*file)

    if err != nil {

    fmt.Println(err.Error())

    return

    }

    fmt.Printf("%x %s\n", md5Value, *file)

    return

    }

    if *directory != "" {

    result, err := Md5SumFolder(*directory)

    if err != nil {

    fmt.Println(err.Error())

    return

    }

    var paths []string

    for path := range result {

    paths = append(paths, path)

    }

    sort.Strings(paths)

    for _, path := range paths {

    fmt.Printf("%x %s\n", result[path], path)

    }

    }

    }

    这里我们根据不同的参数类型进行处理,对于文件的话,我们按照第一个例子中的处理方式调用Md5SumFile()函数获得文件相应的md5值,而如果是文件夹类型的话,我们则需要新建一个处理函数,并且这个处理函数的返回值应该包含文件夹中所有文件和对应的md5值。

    2.2 文件夹函数处理

    整个的文件夹的处理函数如下面所示,包含了文件的遍历和调用md5取值的过程,最终的结果保存在一个map类型中返回。

    func Md5SumFolder(folder string) (map[string][md5.Size]byte, error) {

    result := make(map[string][md5.Size]byte)

    err := filepath.Walk(folder, func(path string, info os.FileInfo, err error) error {

    if err != nil {

    return err

    }

    if !info.Mode().IsRegular() {

    return nil

    }

    data, err := ioutil.ReadFile(path)

    if err != nil {

    return err

    }

    result[path] = md5.Sum(data)

    return nil

    })

    if err != nil {

    return nil, err

    }

    return result, nil

    }

    2.3 汇总处理结果

    我们还需要对于所有的文件md5值进行合并并且计算一个最终的md5值,这样我们只需要监测这个md5值是否发生变化,就能知道这个文件夹是否发生了变化。这里我们新加入一个-merge参数代表了输出单一的合并后的值,否则则输出整个文件夹下所有的md5值。

    //init函数

    merge = flag.Bool("merge", false, "Merging all md5 values to one (Folder type only)")

    ...

    //main函数

    if *merge == true {

    var md5value string

    for _, path := range paths {

    md5value += fmt.Sprintf("%x", result[path])

    }

    fmt.Printf("%x %s\n", md5.Sum([]byte(md5value)), *directory)

    } else {

    for _, path := range paths {

    fmt.Printf("%x %s\n", result[path], path)

    }

    }

    这样我们可以测试函数执行情况如下,分别对于不同的类型参数进行取值:

    $ go run src/md5_folder_support.go -f src/test.txt

    01f73475c6d686cc2efd74a7c2a96df5 src/test.txt

    $ go run src/md5_folder_support.go -d src

    4adea23a39f58672f0258980d6c4208 src/md5_folder_support.go

    fc3ff98e8c6a0d3087d515c0473f8677 src/test.txt

    c7a96525778ec2daefb3e57c99b8c6c2 src/test/hello

    7b9e14080b072115f287a7608d3b4aff src/test/test_sub/hello

    de8ce01552ee663717249956f664c1f6 src/version/md5_files.go

    $ go run src/md5_folder_support.go -d src -merge

    b38c907db04043c7508b464378a5f632 src

    3并行化取值

    3.1 串行测试

    如果只是使用上述的执行程序其实与直接编写一个shell脚本没什么太多区别,我们实测一个大小500Mb的文件夹的执行时间:

    $ ./md5_folder_support -d /home/mike/Calibre\ 书库 -merge

    d9c08b4a6149cb8d57740bd4482a820e /home/mike/Calibre 书库

    1.36595528s

    如果使用shell来直接执行的话,测试脚本如下:

    $ start=$(date +'%s%N');find /home/mike/Calibre\ 书库 -type f -exec md5sum {} \;|sort -k 2|md5sum ;eclipe=$((($(date +'%s%N')-$start)));echo "$eclipe/1000000000"|bc -l

    1.40261921400000000000

    由于shell传递的是整个的sort产生的结果到md5所以显示的会不一致,但是流程基本上都涉及了,对于单个文件的取值,对于结果的排序,和汇总输出。我们可以看到基本上输出的花费时间是差不多的。

    3.2 并行程序执行

    我们将上面的串行执行程序,利用go的并行处理方式进行改写,改写后的文件夹处理函数代码如下:

    func Md5SumFolder(folder string) (map[string][md5.Size]byte, error) {

    returnValue := make(map[string][md5.Size]byte)

    done := make(chan struct{})

    defer close(done)

    c := make(chan result)

    errc := make(chan error,1)

    var wg sync.WaitGroup

    go func() {

    err := filepath.Walk(folder, func(path string, info os.FileInfo, err error) error {

    if err != nil {

    return err

    }

    if !info.Mode().IsRegular() {

    return nil

    }

    wg.Add(1)

    go func() {

    data, err := ioutil.ReadFile(path)

    select {

    case c

    case

    }

    wg.Done()

    }()

    select {

    case

    return errors.New("Canceled")

    default:

    return nil

    }

    })

    errc

    go func() {

    wg.Wait()

    close(c)

    }()

    }()

    for r := range c {

    if r.err != nil {

    return nil, r.err

    }

    returnValue[r.path] = r.md5Sum

    }

    if err :=

    return nil, err

    }

    return returnValue, nil

    }

    我们利用了sync包中的函数来完成等待过程,防止并行程序的提前退出。利用了一个名为done的channel来管理程序的退出,不管任何情况下,该通道的都会随着函数的退出而执行关闭操作,不再接收任何的输入进来。程序如下片段中,我们对于每一个新的文件,利用wg.Add()添加一个占位,这样如果我们不去手动的执行一个wg.Done()则主程序就会停止在wg.Wait()处。

    wg.Add(1)

    go func() {

    data, err := ioutil.ReadFile(path)

    select {

    case c

    case

    }

    wg.Done()

    }()

    对于程序执行一次跟之前相同的运算可以看出,新的并行程序的执行速度已经明显得到提升

    go run src/main.go -d /home/mike/Calibre\ 书库 -merge

    d9c08b4a6149cb8d57740bd4482a820e /home/mike/Calibre 书库

    279.154729ms

    3.3 并行限制

    上述的例子中我们并未限制打开的文件数量,比如我们文件夹下有上万个文件,这样读入内存中的数据可能会非常的大,计算起来也要耗尽所有的内存,因此我们限制我们最大的读取数量比如限制最大打开10个文件进行计算,这样我们的程序需要重新设计一下。

    我们先看一下程序最终实际的运行效果,基本上按照预期的时间处理完毕:

    $ go run src/main.go -d /home/mike/Calibre\ 书库 -merge -max 1

    d9c08b4a6149cb8d57740bd4482a820e /home/mike/Calibre 书库

    1.241248438s

    $ go run src/main.go -d /home/mike/Calibre\ 书库 -merge -max 2

    d9c08b4a6149cb8d57740bd4482a820e /home/mike/Calibre 书库

    831.018648ms

    $ go run src/main.go -d /home/mike/Calibre\ 书库 -merge -max 3

    d9c08b4a6149cb8d57740bd4482a820e /home/mike/Calibre 书库

    520.293084ms

    $ go run src/main.go -d /home/mike/Calibre\ 书库 -merge

    d9c08b4a6149cb8d57740bd4482a820e /home/mike/Calibre 书库

    228.959296ms

    4 最终程序清单如下

    package main

    import (

    "crypto/md5"

    "errors"

    "flag"

    "fmt"

    "io/ioutil"

    "os"

    "path/filepath"

    "sort"

    "sync"

    "time"

    )

    var directory, file *string

    var merge *bool

    var limit *int

    func init() {

    directory = flag.String("d", "", "The directory contains all the files that need to calculate the md5 value")

    file = flag.String("f", "", "The file that need to caclulate the md5 value")

    merge = flag.Bool("merge", false, "Merging all md5 values to one (Folder type only)")

    limit = flag.Int("max",0, "limit the max files to caclulate.")

    }

    func Md5SumFile(file string) (value [md5.Size]byte, err error) {

    data, err := ioutil.ReadFile(file)

    if err != nil {

    return

    }

    value = md5.Sum(data)

    return

    }

    type result struct {

    path string

    md5Sum [md5.Size]byte

    err error

    }

    func Md5SumFolder(folder string, limit int) (map[string][md5.Size]byte, error) {

    returnValue := make(map[string][md5.Size]byte)

    var limitChannel chan (struct{})

    if limit !=0 {

    limitChannel = make(chan struct{}, limit)

    }

    done := make(chan struct{})

    defer close(done)

    c := make(chan result)

    errc := make(chan error,1)

    var wg sync.WaitGroup

    go func() {

    err := filepath.Walk(folder, func(path string, info os.FileInfo, err error) error {

    if err != nil {

    return err

    }

    if !info.Mode().IsRegular() {

    return nil

    }

    if limit !=0 {

    //如果已经满了则阻塞在这里

    limitChannel

    }

    wg.Add(1)

    go func() {

    data, err := ioutil.ReadFile(path)

    select {

    case c

    case

    }

    if limit !=0 {

    //读出数据,这样就有新的文件可以处理

    }

    wg.Done()

    }()

    select {

    case

    return errors.New("Canceled")

    default:

    return nil

    }

    })

    errc

    go func() {

    wg.Wait()

    close(c)

    }()

    }()

    for r := range c {

    if r.err != nil {

    return nil, r.err

    }

    returnValue[r.path] = r.md5Sum

    }

    if err :=

    return nil, err

    }

    return returnValue, nil

    }

    func main() {

    timeStart := time.Now()

    flag.Parse()

    if *directory == "" && *file == "" {

    flag.Usage()

    return

    }

    if *file != "" {

    md5Value, err := Md5SumFile(*file)

    if err != nil {

    fmt.Println(err.Error())

    return

    }

    fmt.Printf("%x %s\n", md5Value, *file)

    return

    }

    if *directory != "" {

    result, err := Md5SumFolder(*directory, *limit)

    if err != nil {

    fmt.Println(err.Error())

    return

    }

    var paths []string

    for path := range result {

    paths = append(paths, path)

    }

    sort.Strings(paths)

    if *merge == true {

    var md5value string

    for _, path := range paths {

    md5value += fmt.Sprintf("%x", result[path])

    }

    fmt.Printf("%x %s\n", md5.Sum([]byte(md5value)), *directory)

    } else {

    for _, path := range paths {

    fmt.Printf("%x %s\n", result[path], path)

    }

    }

    }

    fmt.Println(time.Since(timeStart).String())

    }

    这就是整个的程序的执行流程,如果有任何问题,请留言告诉我或者email给我,我的个人网站jsmean.com欢迎大家访问。

    展开全文
  • 使用Go语言完成文件夹MD5计算

    千次阅读 2016-12-20 14:14:23
    案例需求:我们的监测系统会...1. 单一文件的md5计算我们首先将需求任务进行分解,既然需要计算文件夹下的所有文件md5值,我们必须先考虑如何实现单一文件的md5值计算。下面就是一个简单的md5求值程序,这里我们通过参

    案例需求:我们的监测系统会定期的检查配置文件的变动,这些配置文件放置在一个独立的文件夹下面,我们可以通过对于整个的文件夹内所有文件进行md5的计算来完成监测,本文就通过Go语言实现了一个命令行工具,完成上述的需求。

    1. 单一文件的md5计算

    我们首先将需求任务进行分解,既然需要计算文件夹下的所有文件md5值,我们必须先考虑如何实现单一文件的md5值计算。

    下面就是一个简单的md5求值程序,这里我们通过参数传递进去需要计算的文件,然后调用go语言提供的内置的crypto包中的函数来完成取值,计算得出的结果使用16进制的方式打印出来。

    package main
    
    import (
        "crypto/md5"
        "fmt"
        "io/ioutil"
        "os"
    )
    
    func Md5SumFile(file string) (value [md5.Size]byte, err error) {
        data, err := ioutil.ReadFile(file)
        if err != nil {
            return
        }
        value = md5.Sum(data)
        return
    }
    func main() {
        if len(os.Args) < 2 {
            fmt.Println("Usage: ./md5file yourfile")
            return
        }
        md5Value, err := Md5SumFile(os.Args[1])
        if err != nil {
            fmt.Println(err.Error())
            return
        }
        fmt.Printf("%x %s\n", md5Value, os.Args[1])
    }

    执行程序输出如下面所示:

    $ go run src/md5_files.go src/test.txt 
    fc3ff98e8c6a0d3087d515c0473f8677 src/test.txt

    2 文件的遍历与计算

    2.1 参数处理

    如果我们传递进去的是一个文件夹则如何处理呢?这里我们先通过改造原始的程序使得程序可以接收不同的参数类型比如-d代表了后面的为一个目录文件,-f代表了传递的是一个文件,这里我们需要借助于golang的flags包来完成参数的解析,解析完毕后我们就可以按照对应的方式处理参数了。

    var directory, file *string
    
    func init() {
        directory = flag.String("d", "", "The directory contains all the files that need to calculate the md5 value")
        file = flag.String("f", "", "The file that need to caclulate the md5 value")
    }
    func main() {
        flag.Parse()
        if *directory == "" && *file == "" {
            flag.Usage()
            return
        }
        if *file != "" {
            md5Value, err := Md5SumFile(*file)
            if err != nil {
                fmt.Println(err.Error())
                return
            }
            fmt.Printf("%x %s\n", md5Value, *file)
            return
        }
        if *directory != "" {
    
            result, err := Md5SumFolder(*directory)
            if err != nil {
                fmt.Println(err.Error())
                return
            }
            var paths []string
            for path := range result {
                paths = append(paths, path)
            }
            sort.Strings(paths)
            for _, path := range paths {
                fmt.Printf("%x %s\n", result[path], path)
            }
        }
    }

    这里我们根据不同的参数类型进行处理,对于文件的话,我们按照第一个例子中的处理方式调用Md5SumFile()函数获得文件相应的md5值,而如果是文件夹类型的话,我们则需要新建一个处理函数,并且这个处理函数的返回值应该包含文件夹中所有文件和对应的md5值。

    2.2 文件夹函数处理

    整个的文件夹的处理函数如下面所示,包含了文件的遍历和调用md5取值的过程,最终的结果保存在一个map类型中返回。

    func Md5SumFolder(folder string) (map[string][md5.Size]byte, error) {
        result := make(map[string][md5.Size]byte)
        err := filepath.Walk(folder, func(path string, info os.FileInfo, err error) error {
            if err != nil {
                return err
            }
            if !info.Mode().IsRegular() {
                return nil
            }
            data, err := ioutil.ReadFile(path)
            if err != nil {
                return err
            }
            result[path] = md5.Sum(data)
            return nil
        })
        if err != nil {
            return nil, err
        }
        return result, nil
    }
    2.3 汇总处理结果

    我们还需要对于所有的文件md5值进行合并并且计算一个最终的md5值,这样我们只需要监测这个md5值是否发生变化,就能知道这个文件夹是否发生了变化。这里我们新加入一个-merge参数代表了输出单一的合并后的值,否则则输出整个文件夹下所有的md5值。

    //init函数
    merge = flag.Bool("merge", false, "Merging all md5 values to one (Folder type only)")
    ...
    //main函数
    if *merge == true {
            var md5value string
            for _, path := range paths {
                md5value += fmt.Sprintf("%x", result[path])
            }
            fmt.Printf("%x %s\n", md5.Sum([]byte(md5value)), *directory)
        } else {
            for _, path := range paths {
                fmt.Printf("%x %s\n", result[path], path)
            }
        }

    这样我们可以测试函数执行情况如下,分别对于不同的类型参数进行取值:

    $ go run src/md5_folder_support.go -f src/test.txt
    01f73475c6d686cc2efd74a7c2a96df5 src/test.txt
    
    $ go run src/md5_folder_support.go -d src
    4adea23a39f58672f0258980d6c4208 src/md5_folder_support.go
    fc3ff98e8c6a0d3087d515c0473f8677 src/test.txt
    c7a96525778ec2daefb3e57c99b8c6c2 src/test/hello
    7b9e14080b072115f287a7608d3b4aff src/test/test_sub/hello
    de8ce01552ee663717249956f664c1f6 src/version/md5_files.go
    
    $ go run src/md5_folder_support.go -d src -merge
    b38c907db04043c7508b464378a5f632 src
    

    3并行化取值

    3.1 串行测试

    如果只是使用上述的执行程序其实与直接编写一个shell脚本没什么太多区别,我们实测一个大小500Mb的文件夹的执行时间:

    $ ./md5_folder_support -d /home/mike/Calibre\ 书库 -merge
    d9c08b4a6149cb8d57740bd4482a820e /home/mike/Calibre 书库
    1.36595528s

    如果使用shell来直接执行的话,测试脚本如下:

    $ start=$(date +'%s%N');find /home/mike/Calibre\ 书库 -type f -exec md5sum {} \;|sort -k 2|md5sum ;eclipe=$((($(date +'%s%N')-$start)));echo "$eclipe/1000000000"|bc -l
    1.40261921400000000000

    由于shell传递的是整个的sort产生的结果到md5所以显示的会不一致,但是流程基本上都涉及了,对于单个文件的取值,对于结果的排序,和汇总输出。我们可以看到基本上输出的花费时间是差不多的。

    3.2 并行程序执行

    我们将上面的串行执行程序,利用go的并行处理方式进行改写,改写后的文件夹处理函数代码如下:

    func Md5SumFolder(folder string) (map[string][md5.Size]byte, error) {
        returnValue := make(map[string][md5.Size]byte)
        done := make(chan struct{})
        defer close(done)
        c := make(chan result)
        errc := make(chan error, 1)
        var wg sync.WaitGroup
        go func() {
            err := filepath.Walk(folder, func(path string, info os.FileInfo, err error) error {
                if err != nil {
                    return err
                }
                if !info.Mode().IsRegular() {
                    return nil
                }
                wg.Add(1)
                go func() {
                    data, err := ioutil.ReadFile(path)
                    select {
                    case c <- result{path: path, md5Sum: md5.Sum(data), err: err}:
                    case <-done:
                    }
                    wg.Done()
                }()
                select {
                case <-done:
                    return errors.New("Canceled")
                default:
                    return nil
                }
            })
            errc <- err
            go func() {
                wg.Wait()
                close(c)
            }()
        }()
        for r := range c {
            if r.err != nil {
                return nil, r.err
            }
            returnValue[r.path] = r.md5Sum
        }
        if err := <-errc; err != nil {
            return nil, err
        }
        return returnValue, nil
    }

    我们利用了sync包中的函数来完成等待过程,防止并行程序的提前退出。利用了一个名为done的channel来管理程序的退出,不管任何情况下,该通道的都会随着函数的退出而执行关闭操作,不再接收任何的输入进来。程序如下片段中,我们对于每一个新的文件,利用wg.Add()添加一个占位,这样如果我们不去手动的执行一个wg.Done()则主程序就会停止在wg.Wait()处。

    wg.Add(1)
    go func() {
        data, err := ioutil.ReadFile(path)
        select {
        case c <- result{path: path, md5Sum: md5.Sum(data), err: err}:
        case <-done:
        }
        wg.Done()
    }()

    对于程序执行一次跟之前相同的运算可以看出,新的并行程序的执行速度已经明显得到提升

    go run src/main.go -d /home/mike/Calibre\ 书库 -merge
    d9c08b4a6149cb8d57740bd4482a820e /home/mike/Calibre 书库
    279.154729ms
    3.3 并行限制

    上述的例子中我们并未限制打开的文件数量,比如我们文件夹下有上万个文件,这样读入内存中的数据可能会非常的大,计算起来也要耗尽所有的内存,因此我们限制我们最大的读取数量比如限制最大打开10个文件进行计算,这样我们的程序需要重新设计一下。

    我们先看一下程序最终实际的运行效果,基本上按照预期的时间处理完毕:

    $ go run src/main.go -d /home/mike/Calibre\ 书库 -merge -max 1
    d9c08b4a6149cb8d57740bd4482a820e /home/mike/Calibre 书库
    1.241248438s
    $ go run src/main.go -d /home/mike/Calibre\ 书库 -merge -max 2
    d9c08b4a6149cb8d57740bd4482a820e /home/mike/Calibre 书库
    831.018648ms
    $ go run src/main.go -d /home/mike/Calibre\ 书库 -merge -max 3
    d9c08b4a6149cb8d57740bd4482a820e /home/mike/Calibre 书库
    520.293084ms
    $ go run src/main.go -d /home/mike/Calibre\ 书库 -merge
    d9c08b4a6149cb8d57740bd4482a820e /home/mike/Calibre 书库
    228.959296ms

    4 最终程序清单如下

    package main
    
    import (
        "crypto/md5"
        "errors"
        "flag"
        "fmt"
        "io/ioutil"
        "os"
        "path/filepath"
        "sort"
        "sync"
        "time"
    )
    
    var directory, file *string
    var merge *bool
    var limit *int
    
    func init() {
        directory = flag.String("d", "", "The directory contains all the files that need to calculate the md5 value")
        file = flag.String("f", "", "The file that need to caclulate the md5 value")
        merge = flag.Bool("merge", false, "Merging all md5 values to one (Folder type only)")
        limit = flag.Int("max", 0, "limit the max files to caclulate.")
    }
    func Md5SumFile(file string) (value [md5.Size]byte, err error) {
        data, err := ioutil.ReadFile(file)
        if err != nil {
            return
        }
        value = md5.Sum(data)
        return
    }
    
    type result struct {
        path   string
        md5Sum [md5.Size]byte
        err    error
    }
    
    func Md5SumFolder(folder string, limit int) (map[string][md5.Size]byte, error) {
        returnValue := make(map[string][md5.Size]byte)
        var limitChannel chan (struct{})
        if limit != 0 {
            limitChannel = make(chan struct{}, limit)
        }
    
        done := make(chan struct{})
        defer close(done)
    
        c := make(chan result)
        errc := make(chan error, 1)
        var wg sync.WaitGroup
        go func() {
            err := filepath.Walk(folder, func(path string, info os.FileInfo, err error) error {
                if err != nil {
                    return err
                }
                if !info.Mode().IsRegular() {
                    return nil
                }
    
                if limit != 0 {
                    //如果已经满了则阻塞在这里
                    limitChannel <- struct{}{}
                }
    
                wg.Add(1)
                go func() {
                    data, err := ioutil.ReadFile(path)
                    select {
                    case c <- result{path: path, md5Sum: md5.Sum(data), err: err}:
                    case <-done:
                    }
                    if limit != 0 {
                        //读出数据,这样就有新的文件可以处理
                        <-limitChannel
                    }
    
                    wg.Done()
                }()
                select {
                case <-done:
                    return errors.New("Canceled")
                default:
                    return nil
                }
            })
            errc <- err
            go func() {
                wg.Wait()
                close(c)
            }()
        }()
        for r := range c {
            if r.err != nil {
                return nil, r.err
            }
            returnValue[r.path] = r.md5Sum
        }
        if err := <-errc; err != nil {
            return nil, err
        }
        return returnValue, nil
    }
    
    func main() {
        timeStart := time.Now()
        flag.Parse()
        if *directory == "" && *file == "" {
            flag.Usage()
            return
        }
        if *file != "" {
            md5Value, err := Md5SumFile(*file)
            if err != nil {
                fmt.Println(err.Error())
                return
            }
            fmt.Printf("%x %s\n", md5Value, *file)
            return
        }
        if *directory != "" {
    
            result, err := Md5SumFolder(*directory, *limit)
            if err != nil {
                fmt.Println(err.Error())
                return
            }
            var paths []string
            for path := range result {
                paths = append(paths, path)
            }
            sort.Strings(paths)
            if *merge == true {
                var md5value string
                for _, path := range paths {
                    md5value += fmt.Sprintf("%x", result[path])
                }
                fmt.Printf("%x %s\n", md5.Sum([]byte(md5value)), *directory)
            } else {
                for _, path := range paths {
                    fmt.Printf("%x %s\n", result[path], path)
                }
            }
    
        }
        fmt.Println(time.Since(timeStart).String())
    }
    

    这就是整个的程序的执行流程,如果有任何问题,请留言告诉我或者email给我,我的个人网站jsmean.com欢迎大家访问。

    展开全文
  • 获取文件夹下所以文件的MD5,包括子文件
  • 查看两个文件是否是同一文件,很好地方法就是计算md5的值,然后比较是否相同。 #-*- coding:utf-8 -*- import os import timeit import multiprocessing import hashlib def getHash(f): # line=f.readline()...

     查看两个文件是否是同一文件,很好地方法就是计算其md5的值,然后比较是否相同。

    #-*- coding:utf-8 -*-
    import os
    import timeit
    import multiprocessing
    import hashlib
    
    
    def getHash(f):
        # line=f.readline()
        md5_hash = hashlib.md5()
        while True:
            # md5_hash.update(line)                                、
            # line=f.readline()
            content = f.read(1024)
            if not content:
                break
            md5_hash.update(content)
        return md5_hash.hexdigest()
    
    
    def readFilename(path, allfile):
        filelist = os.listdir(path)
    
        for filename in filelist:
            filepath = os.path.join(path, filename)
            #filepath=unicode(filepath,"utf-8")
    
            if os.path.isdir(filepath):
                readFilename(filepath, allfile)
            else:
                allfile.append(filepath)
    
        return allfile
    
    
    def begin():
        ff1 = "C:\Users\zgd\Desktop\zgddgz"
        ff2 = "C:\Users\zgd\Desktop\gdzhang"
        allJPG1=[]
        allJPG1=readFilename(ff1, allJPG1)
        # print allJPG1
    
        allJPG2=[]
        allJPG2=readFilename(ff2, allJPG2)
        # print allJPG2
    
        count=0
        for a1 in allJPG1:
            for b1 in allJPG2:
                # print a1,b1
                with open(a1, 'r') as f1, open(b1, 'r') as f2:
                    m1 = getHash(f1)
                    # print m1
                    m2 = getHash(f2)
                    # print m2
    
                if m1 == m2:
                    count=count+1
                    print count
                    print "%s = %s"% (a1,b1)
    
                    filepath= 'C:\Users\zgd\Desktop\zhangniu\Link.txt'
                    # filepath = 'H:\\RINS1000\\' + 'Link.txt'
                    with open(filepath,'a') as fp:
                        fp.write(a1+"\t\t")
                        fp.write(b1.split("\\")[-1] +"\n")
    
                    fp.close()
                f1.close()
                f2.close()
    
    if __name__ == '__main__':
        start = timeit.default_timer()
    
        pool = multiprocessing.Pool(32)
        pool.apply(func = begin)
        pool.close()
        pool.join()
    
        end = timeit.default_timer()
        print str(end - start)

     

    展开全文
  • python计算字符串、文件、文件夹MD5,包含三个功能函数,供参考使用
  • 主要介绍了Ruby遍历文件夹同时计算文件的md5sum,本文直接给出实现代码,需要的朋友可以参考下
  • 我有一个文件夹下有好几个文件!我现在要对这个文件夹进行MD5值计算?? 请问要怎么实现啊!网上很多都是对一个文件的进行MD5值进行计算的! 我这要对文件夹下所有文件进行一个MD5计算???
  • md5计算工具

    2015-05-26 11:08:03
    来自haozip的md5计算工具,拖拽文件或文件夹快速计算md5,sha1 crc值等,绿色免安装
  • Easy MD5计算文件、目录及子目录下所有文件的MD5摘要码,您可以以命令行方式运 行Easy MD5,将文件或目录名作为参数传入,也可以在Windows资源管理器中将文件或目 录图标拖入Easy MD5窗口或Easy MD5程序图标上,...
  •  System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();  byte[] retVal = md5.ComputeHash(file);  file.Close();    StringBuilder sb = new ...

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.IO;

    namespace test
    {
        class Program
        {
            static FileStream fs;
            static StreamWriter sw;

            static void Main(string[] args)
            {
                DeleteFile("E:\\A.txt");
                fs= new FileStream("E:\\A.txt",FileMode.Create);
                sw= new StreamWriter(fs,Encoding.Default);
                FindFoldersAndFiles(@"E:\Program Files");
                sw.Close();
                fs.Close();
            }

            //递归目标文件夹中的所有文件和文件夹
            private static void FindFoldersAndFiles(string path)
            {
                //Console.WriteLine("文件夹" + path);
                sw.WriteLine(path);
                //遍历目标文件夹的所有文件
                foreach (string fileName in Directory.GetFiles(path))
                {
                    //Console.WriteLine("┣" + fileName);
                    sw.WriteLine(fileName + " " + GetMD5HashFromFile(fileName));
                }

                //遍历目标文件夹的所有文件夹
                foreach (string directory in Directory.GetDirectories(path))
                {
                    FindFoldersAndFiles(directory);
                }
            }

            private static string GetMD5HashFromFile(string fileName)
            {
                 FileStream file = new FileStream(fileName, FileMode.Open);
                 System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
                 byte[] retVal = md5.ComputeHash(file);
                 file.Close();
     
                StringBuilder sb = new StringBuilder();
                 for (int i = 0; i < retVal.Length; i++)
                 {
                    sb.Append(retVal[i].ToString("x2"));
                 }
                 return sb.ToString();
             }

            private static bool DeleteFile(string path)
            {
                if (File.Exists(path))
                {
                    //如果存在则删除
                    File.Delete(path);
                    return true;
                }
                return false;
            }
        }
    }
     

    展开全文
  • ruby遍历文件夹计算md5sum

    千次阅读 2012-12-17 10:10:30
    #!/usr/bin/ruby -w # require 'digest/md5' if ARGV.empty? puts "usgae: #$0 path" exit 0 end dir_name=ARGV.shift def dir_md5sum(path) md5s=Array.new if File.directory?
  • """查看文件夹下的所有文件及文件夹""" def Look_File(path): for root , dirs, files in os.walk(path, True): for item in files: #主目录下的文件夹 ..."""计算文件夹 大小""" def FileSize(p...

空空如也

空空如也

1 2 3 4 5 ... 16
收藏数 312
精华内容 124
关键字:

md5计算文件夹