Как перемещаться по каталогам и обрабатывать файлы?ruby-91

Ruby предоставляет несколько мощных инструментов для работы с файловой системой. Рассмотрим основные методы навигации и обработки файлов.

1. Базовые операции с каталогами

Получение текущей рабочей директории

current_dir = Dir.pwd
puts "Текущая директория: #{current_dir}"

Изменение текущей директории

Dir.chdir("/path/to/directory") do
  puts "Теперь мы в: #{Dir.pwd}"
  # Все операции здесь будут в новой директории
end
# После блока вернемся в исходную директорию

Создание директории

Dir.mkdir("new_folder") # Создает одну директорию
Dir.mkdir_p("path/to/nested/folders") # Создает всю цепочку директорий

2. Навигация по файловой системе

Получение списка файлов и директорий

# Все элементы в директории
entries = Dir.entries(".") # Включая . и ..
files_and_dirs = Dir.children(".") # Только имена, без . и ..

# Только файлы с определенным расширением
ruby_files = Dir.glob("*.rb")

Рекурсивный поиск файлов

# Все ruby файлы во всех поддиректориях
all_ruby_files = Dir.glob("**/*.rb")

# С учетом скрытых файлов (начинающихся с точки)
all_files = Dir.glob("**/*", File::FNM_DOTMATCH)

3. Обработка файлов

Обход всех файлов в директории

Dir.each_child(".") do |entry|
  next if File.directory?(entry)
  puts "Обрабатываем файл: #{entry}"
  # Ваша обработка файла
end

Чтение и обработка нескольких файлов

Dir.glob("data/*.csv").each do |csv_file|
  puts "Обработка #{csv_file}"
  data = File.read(csv_file)
  # Дальнейшая обработка
end

4. Фильтрация файлов

По размеру

large_files = Dir.glob("*").select do |f|
  File.file?(f) && File.size(f) > 1_000_000 # > 1MB
end

По времени модификации

recent_files = Dir.glob("*").select do |f|
  File.file?(f) && File.mtime(f) > Time.now - 86400 # Изменены за последние 24 часа
end

5. Рекурсивная обработка директорий

Собственная реализация

def process_directory(path)
  Dir.each_child(path) do |entry|
    full_path = File.join(path, entry)
    if File.directory?(full_path)
      process_directory(full_path) # Рекурсивный вызов
    else
      process_file(full_path) # Обработка файла
    end
  end
end

С использованием Find

require 'find'

Find.find("/path/to/start") do |path|
  if File.file?(path)
    puts "Найден файл: #{path}"
    # Обработка файла
  end
end

6. Практические примеры

Поиск дубликатов файлов

require 'digest'

files_by_size = Dir.glob("**/*", File::FNM_DOTMATCH)
                .select {|f| File.file?(f)}
                .group_by {|f| File.size(f)}

files_by_size.each do |size, files|
  next if files.size == 1

  # Для файлов одинакового размера считаем хеш
  files.group_by {|f| Digest::MD5.file(f).hexdigest}.each do |hash, dups|
    puts "Дубликаты: #{dups.join(', ')}" if dups.size > 1
  end
end

Пакетное переименование файлов

Dir.glob("photos/*.jpg").each_with_index do |file, index|
  new_name = "vacation_#{index + 1}.jpg"
  File.rename(file, File.join(File.dirname(file), new_name))
end

7. Безопасность и лучшие практики

  1. Всегда проверяйте существование файлов:

    if File.exist?(path)
      # Обработка
    end
    
  2. Используйте File.join для создания путей:

    path = File.join("dir", "subdir", "file.txt")
    
  3. Обрабатывайте исключения:

    begin
      Dir.mkdir("new_dir")
    rescue Errno::EEXIST
      puts "Директория уже существует"
    end
    
  4. Для сложных операций используйте Pathname:

    require 'pathname'
    pn = Pathname.new("/path/to/file")
    puts pn.dirname, pn.basename, pn.extname
    

Резюмируем

Для работы с файловой системой в Ruby есть все необходимые инструменты:

  • Класс Dir для операций с каталогами
  • Методы glob и find для поиска файлов
  • Различные способы рекурсивной обработки
  • Возможности фильтрации по разным критериям
  • Важно соблюдать безопасность и использовать абсолютные пути для критических операций
  • Для сложных задач удобно использовать комбинацию Dir.glob, File методов и Pathname