我正在编写脚本,我需要遍历文件系统,并返回文件的SHA1总和。
我使用的代码是:
time ruby -r'digest/sha1' -r'find' -e 'Find.find("/") {|x| next unless File.file?(x) ; Digest::SHA1.hexdigest(File.read(x))}
问题是,我在执行后约5秒后收到此错误消息
-e:1:in `read': failed to allocate memory (NoMemoryError)
from -e:1:in `open'
from -e:1:in `block in <main>'
from /usr/share/ruby/find.rb:43:in `block in find'
from /usr/share/ruby/find.rb:42:in `catch'
from /usr/share/ruby/find.rb:42:in `find'
from -e:1:in `<main>'
为什么我会收到此错误,以及&#34;最佳做法&#34;处理这样的任务?
帮助表示赞赏。
答案 0 :(得分:2)
它似乎没有很好的文档记录(或者至少,我没有在写入位置查找)但是Digest库提供了一种通过读取块中的文件并计算文件来对文件进行哈希编码的方法hashsum,而File.read将整个文件读入内存。
工作代码为:
begin
Find.find("/") do |file|
next unless File.file?(file)
puts "#{Digest::SHA1.file(file)} #{file}"
end
rescue => e
puts e
end
答案 1 :(得分:1)
为什么把它放在一个单行程中会让它变得困难? 如果你把你的代码放在这样的脚本中,那么在我的系统上,每次运行都会顺利进行,并且我的HD上的每个文件都会被读取。 在数据磁盘上你最好找到一种处理大文件的方法,比如https://www.ruby-forum.com/topic/58563我适用于SHA1的解决方案。
require 'digest/sha1'
require 'find'
Find.find("/") do |file|
next unless File.file?(file)
begin
sha = File.open(file, 'rb') do |io|
dig = Digest::SHA1.new
buf = ""
dig.update(buf) while io.read(4096, buf)
dig
end
puts "#{sha} #{file}"
rescue => e
puts e.backtrace
end
end
给出
ba4aeced8ab461b75ff87d989ff16ca2464ea787 /$AVG/$VAULT/vault.db
31d8730390451d236b80c4351b6b287d6853570c /$AVG/$VAULT/vvfolder.idx
b4c783e3478e5b6f795e92d3cf5d85837fffd128 /$Recycle.Bin/S-1-5-21-50811273-296787125-2640436092-1000/desktop.ini
b4c783e3478e5b6f795e92d3cf5d85837fffd128 /$Recycle.Bin/S-1-5-21-50811273-296787125-2640436092-1011/desktop.ini
3109805dcc447395f58fec8b5e8a8fca1d20892b /.rnd
61fc34796b7cc67caf9da685e59461c9d13fba29 /4nt500/4NT.INI
...