Ruby Dir 类和方法(长文解析)

更新时间:

💡一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

  • 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...点击查看项目介绍 ;
  • 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;

截止目前, 星球 内专栏累计输出 82w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 2900+ 小伙伴加入学习 ,欢迎点击围观

前言

在 Ruby 编程中,处理文件和目录的操作是许多项目的基础需求。无论是开发自动化脚本、构建文件管理系统,还是处理静态网站生成,Ruby Dir 类和方法都是不可或缺的工具。Dir 类提供了丰富的接口,帮助开发者高效地遍历目录、筛选文件、创建或删除文件夹,甚至实现复杂的文件系统操作。

本文将从基础概念出发,逐步深入讲解 Dir 类的核心方法,并通过实际案例展示其应用场景。无论是编程新手还是有一定经验的开发者,都能通过本文掌握 Dir 类的使用技巧,提升对 Ruby 文件系统操作的理解。


Dir 类的基本概念

什么是 Dir 类?

Dir 类是 Ruby 标准库中的一个核心类,用于操作操作系统中的目录。它可以视为一个“文件系统导航工具”,帮助开发者通过编程方式与文件系统交互。例如:

  • 遍历目录:逐个读取目录中的文件或子目录。
  • 筛选文件:根据名称、扩展名或其他条件过滤文件。
  • 创建或删除目录:动态管理文件夹结构。

Dir 类的分类:类方法与实例方法

Dir 类的方法分为两类:

  1. 类方法:直接通过 Dir. 调用,例如 Dir.globDir.foreach
  2. 实例方法:需要先创建 Dir 的实例,例如通过 Dir.new 初始化后调用 readclose

类方法 vs 实例方法的比喻

可以将类方法想象为“快捷工具”,它们提供了一站式解决方案;而实例方法则像“手动操作”,需要开发者更细致地控制流程。例如:

  • Dir.glob("*.rb")(类方法)直接返回所有 .rb 文件的列表。
  • Dir.new("path").each { |f| ... }(实例方法)需要手动遍历每个文件。

核心方法详解

1. Dir.glob:文件模式匹配

Dir.glob 是最常用的方法之一,用于根据通配符模式(如 ***)匹配文件或目录。

语法

Dir.glob(pattern, flags = 0)  

参数说明

  • pattern:匹配模式字符串,支持以下通配符:
    • *:匹配任意字符(单级目录)。
    • **:匹配多级子目录(Ruby 2.5+)。
    • ?:匹配单个字符。
  • flags:可选的标志位,例如 File::FNM_CASEFOLD 忽略大小写。

示例代码

rb_files = Dir.glob("*.rb")  
puts rb_files.inspect  

text_files = Dir.glob("documents/**/*.txt")  
puts text_files.inspect  

实际案例:过滤日志文件

假设有一个 logs 目录,需要筛选出最近一周的 *.log 文件:

require 'date'  

logs = Dir.glob("logs/*.log")  
recent_logs = logs.select do |file|  
  File.mtime(file) > 7.days.ago # 假设 `days.ago` 是时间辅助方法  
end  
puts "最近一周的日志:#{recent_logs}"  

2. Dir.foreach:逐个遍历目录

Dir.foreach 方法逐个读取目录中的文件名,适合需要逐项处理的场景。

语法

Dir.foreach(directory) { |entry| ... }  

示例代码

Dir.foreach(".") do |file|  
  puts "文件名:#{file}"  
  # 输出包括 "."(当前目录)和 ".."(父目录),需过滤掉  
  next if file.start_with?(".")

  puts "文件大小:#{File.size(file)} bytes" if File.file?(file)  
end  

注意事项

  • 默认会包含 ...,需通过条件语句过滤。
  • 如果目录为空,返回空数组。

3. Dir.entries:获取目录条目列表

Dir.entries 返回目录中所有条目(包括 ...)的数组。

语法

Dir.entries(directory)  

示例代码

entries = Dir.entries("projects")  
filtered_entries = entries.reject { |e| e.start_with?(".") }  
puts "有效文件和子目录:#{filtered_entries}"  

对比 foreachentries

  • foreach 是迭代器,适合边读边处理。
  • entries 返回完整列表,适合需要整体操作的场景。

4. Dir.new:手动管理目录遍历

通过 Dir.new 创建 Dir 实例,可以更精细地控制遍历过程,例如:

dir = Dir.new("images")  
begin  
  while entry = dir.read  
    puts "当前条目:#{entry}" unless entry.start_with?(".")  
  end  
ensure  
  dir.close # 必须显式关闭  
end  

特点与限制

  • 需要手动调用 readclose
  • 适合需要多次读取或嵌套遍历的场景。

5. Dir.mkdirDir.delete:创建与删除目录

创建目录

Dir.mkdir("new_folder") # 创建单级目录  
Dir.mkdir("parent/child", 0755) # 指定权限模式  

递归创建目录(Dir.mkpath

Dir.mkpath("a/b/c") # 确保路径中的所有层级被创建  

删除目录

Dir.delete("empty_folder") # 目录必须为空  
Dir.rmdir("another_empty") # 与 `delete` 功能相同  

安全删除非空目录(FileUtils 辅助)

require 'fileutils'  
FileUtils.rm_rf("non_empty_dir") # 递归删除目录及内容  

进阶用法与案例

案例 1:遍历并统计目录大小

def calculate_dir_size(path)  
  total = 0  
  Dir.foreach(path) do |entry|  
    next if entry.start_with?(".")  

    full_path = File.join(path, entry)  
    if File.directory?(full_path)  
      total += calculate_dir_size(full_path)  
    else  
      total += File.size(full_path)  
    end  
  end  
  total  
end  

puts "当前目录总大小:#{calculate_dir_size(".") / 1024} KB"  

案例 2:批量重命名文件

Dir.glob("old_names/*.jpg").each do |file|  
  new_name = File.basename(file, ".jpg").upcase + ".JPG"  
  File.rename(file, File.join("new_names", new_name))  
end  

案例 3:递归搜索特定扩展名

def find_files(pattern, dir = ".")  
  results = []  
  Dir.foreach(dir) do |entry|  
    next if entry.start_with?(".")  

    full_path = File.join(dir, entry)  
    if File.directory?(full_path)  
      results.concat(find_files(pattern, full_path))  
    elsif File.fnmatch(pattern, entry)  
      results << full_path  
    end  
  end  
  results  
end  

puts find_files("*.md", "docs").inspect  

常见问题与注意事项

1. 权限问题

操作目录时需确保程序有足够权限,例如:

begin  
  Dir.mkdir("/system/protected")  
rescue Errno::EACCES => e  
  puts "权限不足:#{e.message}"  
end  

2. 路径的相对与绝对

  • 相对路径(如 "logs")基于当前工作目录。
  • 绝对路径(如 "/var/log")需以 / 开头。

3. 处理符号链接

Ruby 默认会跟随符号链接,若需排除,可结合 File.symlink? 判断:

Dir.foreach(".") do |entry|  
  next if File.symlink?(entry)  
  # ...  
end  

4. 性能优化

对于超大目录,Dir.foreachDir.entries 更节省内存,因前者逐个读取而非一次性加载所有条目。


结论

通过本文,我们系统学习了 Ruby Dir 类和方法 的核心功能与实践案例。从基础的 globforeach,到进阶的递归遍历和目录管理,Dir 类为开发者提供了灵活高效的文件系统操作工具。

无论是自动化脚本开发、日志处理,还是文件管理系统的构建,掌握 Dir 类的方法是提升 Ruby 开发效率的关键。建议读者通过实际项目练习,例如实现一个文件整理工具或统计脚本,将理论转化为实践。

未来,随着 Ruby 生态的持续发展,Dir 类的功能可能进一步扩展。保持对新版本的更新关注,结合 FileUtils 等辅助库,开发者可以更轻松地应对复杂的文件系统挑战。

最新发布