Tcl:检查两个文件之间的相同内容

Tcl: Check for same content between two files

我有一个用 vimscript 编写的程序,它检查两个文件是否相同。它对 diff 进行系统调用以验证它们是否不同。

我在 Tcl 中需要类似的东西,但不求助于外部命令或系统调用。我不需要知道文件之间的差异或进行比较,如果两个文件具有相同的内容则为 return 1,如果内容不同则为 0。

proc comp_file {file1 file2} {
    # optimization: check file size first
    set equal 0
    if {[file size $file1] == [file size $file2]} {
        set fh1 [open $file1 r]
        set fh2 [open $file2 r]
        set equal [string equal [read $fh1] [read $fh2]]
        close $fh1
        close $fh2
    }
    return $equal
}

if {[comp_file /tmp/foo /tmp/bar]} {
    puts "files are equal"
}

对于直接的二进制比较,您可以一次只处理一个块。 (尽管您可以选择更大的值,但每个块 4kB 可能已经足够了;I/O 开销在任何情况下都将占主导地位。)最简单的表达方式是在 try…[=14= 中使用循环](需要 Tcl 8.6):

proc sameContent {file1 file2} {
    set f1 [open $file1 "rb"]
    set f2 [open $file2 "rb"]
    try {
        while 1 {
            if {[read $f1 4096] ne [read $f2 4096]} {
                return 0
            } elseif {[eof $f1]} {
                # The same if we got to EOF at the same time
                return [eof $f2]
            } elseif {[eof $f2]} {
                return 0
            }
        }
    } finally {
        close $f1
        close $f2
    }
}

否则,我们可以利用这样一个事实,即我们可以查看是否已设置变量以保持逻辑相当简单(这不太清楚)来制作适用于旧版本 Tcl 的代码:

proc sameContent {file1 file2} {
    set f1 [open $file1]
    fconfigure $f1 -translation binary
    set f2 [open $file2]
    fconfigure $f2 -translation binary
    while {![info exist same]} {
        if {[read $f1 4096] ne [read $f2 4096]} {
            set same 0
        } elseif {[eof $f1]} {
            # The same if we got to EOF at the same time
            set same [eof $f2]
        } elseif {[eof $f2]} {
            set same 0
        }
    }
    close $f1
    close $f2
    return $same
}

两者的调用方式相同:

if {[sameContent "./foo.txt" "some/dir/bar.txt"]} {
    puts "They're the same contents, byte-for-byte"
} else {
    puts "A difference was found"
}