如何在同一目录中查找文本文件

时间:2016-05-31 22:36:02

标签: ruby file io

我试图以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

2 个答案:

答案 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实用程序(例如catgrep都会使用此方法。

接受命令行选项以查找数据文件

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')