我试图以CSV格式阅读1880年的婴儿名单。我的程序,当在OS X上的终端中运行时返回一个错误,指示yob1880.txt不存在。
No such file or directory @ rb_sysopen - /names/yob1880.txt (Errno::ENOENT)
from names.rb:2:in `<main>'
脚本和文本文件的位置为/Users/*****/names
。
lines = []
File.expand_path('../yob1880.txt', __FILE__)
IO.foreach('../yob1880.txt') do |line|
lines << line
if lines.size >= 1000
lines = FasterCSV.parse(lines.join) rescue next
store lines
lines = []
end
end
store lines
答案 0 :(得分:1)
如果您从/Users/*****/names
目录运行脚本,并且文件也存在,那么您只需删除&#34; ../"来自您的路径名,以防止在/Users/*****
中查找文件。
使用此方法引用您的文件,而不是:
File.expand_path('yob1880.txt', __FILE__)
IO.foreach('yob1880.txt') do |line|
请注意,File.expand_path
目前无效,因为没有捕获或用于任何目的的返回值;它只是在执行时消耗资源。根据您的实际意图,可以实际删除它。
更深入地讨论这个主题,脚本可能更好地明确它找到文件的目录。考虑这些方法:
Dir.chdir(File.dirname(File.expand_path(__FILE__)))
IO.foreach('yob1880.txt') do |line|
这明确要求脚本和数据相对于彼此存储;在这种情况下,它们将存储在同一目录中。
# do not use Dir.chdir or File.expand_path
IO.foreach('/Users/****/yob1880.txt') do |line|
如果脚本在一个小的,包含的环境(例如您自己的计算机)中使用,但如果将数据移动到另一个目录或另一台计算机,则会很脆弱。通常,除了用于个人用途的短期脚本之外,这种方法没有用。
永远不要将使用此方法的脚本投入生产使用。
# do not use Dir.chdir or File.expand_path
IO.foreach('yob1880.txt') do |line|
如果从存在数据的目录运行脚本,这将起作用,但如果从另一个目录运行则会失败。当脚本检测到目录的内容时,这种方法通常效果更好,而不是要求某些文件已经存在。
如果命令行选项不会覆盖此类行为,则许多Linux / Unix实用程序(例如cat
和grep
都会使用此方法。
require 'optparse'
base_directory = "."
OptionParser.new do |opts|
opts.banner = "Usage: example.rb [options]"
opts.on('-d', '--dir NAME', 'Directory name') {|v| base_directory = Dir.chdir(File.dirname(File.expand_path(v))) }
end
IO.foreach(File.join(base_directory, 'yob1880.txt')) do |line|
# do lines
end
这将为您的脚本提供-d
或--dir
选项,以指定查找文件的目录。
此代码允许您使用YAML配置文件来定义文件的位置:
require 'yaml'
config_filename = File.expand_path("~/yob/config.yml")
config = {}
name = nil
config = YAML.load_file(config_filename)
base_directory = config["base"]
IO.foreach(File.join(base_directory, 'yob1880.txt')) do |line|
# do lines
end
这并不包括与查找和加载配置文件相关的任何错误处理,但它得到了重点。有关使用带错误处理的YAML配置文件的其他信息,请参阅Asking user for information, and never having to ask again上的答案。
您可以使用工具来确定查找数据文件的方法。您甚至可以使用混合搭配解决方案来实现更复杂的解决方案。例如,当没有配置文件时,您可以默认使用当前目录(或脚本目录),并在必要时允许命令行选项手动覆盖目录。
答案 1 :(得分:1)
当我想要为我的脚本规范化当前工作目录时,我总是使用这种技术。这是一个好主意,因为在大多数情况下,您可以编写脚本代码并将支持文件放在同一文件夹中,或放在主脚本的子文件夹中。
这会将当前工作目录重置为与脚本所在位置相同的文件夹。之后,更容易找出所有内容的路径:
# Reset working directory to same folder as current script file
Dir.chdir(File.dirname(File.expand_path(__FILE__)))
之后,您只需打开数据文件:
IO.foreach('yob1880.txt')