我有一个我在vimscript中创建的程序,它检查两个文件是否相同。它向diff
进行系统调用,以验证它们是否是不同的。
我需要在Tcl中使用类似的东西,但不需要使用外部命令或系统调用。我不需要知道差异或文件之间的比较,如果两个文件具有相同的内容则返回1,如果内容不同则返回0。
答案 0 :(得分:3)
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
}
答案 1 :(得分:2)
对于直接二进制比较,您可以一次只处理一个块。 (虽然你可以选择更大的值,4kB可能已经足够了;但I / O开销在任何情况下都会占主导地位。)表达这一点的最简单方法是使用try
... finally
内的循环(需要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"
}