Работа с файловой системой в Ruby ч. 3: Стандартная библиотека Ruby: FileUtils и Pathname
июля 4, 2011 | Published in Ruby, Основы
Продолжая серию статей о File IO в Ruby, мы, в этой статье покопаемся в двух компонентах стандартной библиотеки языка Ruby, которые расширяют ядро Ruby IO API: модуль FileUtils и класс Pathname.
Модуль FileUtils
Модуль FileUtils предоставляет интересный подход к манипуляции файлами путем эмуляции множества команд Unix для работы с файлами и большинства их опций (флагов). То, что вы можете сделать командами типа rm -rf и ln -s может быть выполнено соответственно методами FileUtils.rb_rf и FileUtils.ln_s.
Так как они придерживаются синтаксиса знакомого большинству Ruby-программистов они являются очень простыми для понимания, делая список вызовов методов FileUtils очень похожим на сеанс bash. Пример, что приведен ниже демонстрирует эту схожесть:
require "fileutils" FileUtils.touch(["some_file.rb", "another_file.rb"]) FileUtils.mkdir("code") FileUtils.mv(["another_file.rb", "../other_file.rb"], "code") Dir["code/*"] #>> ["code/some_file.rb", "code/another_file.rb"] FileUtils.cp_r("code", "bkp") FileUtils.rm_r("code") Dir["code/*"] #>> [] Dir["bkp/*"] #>> ["bkp/some_file.rb", "bkp/another_file.rb"]
Как и многие команды Unix, многие методы FileUtils знают как работать с множеством файлов которое передано параметром в виде массива, например, метод FileUtils.cp. Они также могут принимать флаги для изменения своего поведения:
require "fileutils" FileUtils.rm("a_file.rb") # removes this file FileUtils.rm(Dir["bkp_*"]) # remove all files that start with bkp FileUtils.rm(Dir["bkp_*"], :verbose => true) #print the equivalent stmt and remove the bkp files
Класс Pathname
Класс Pathname занимается представлением пути, размещения файла в файловой системе и предоставляет возможности для запрашивания и манипулирования данными пути.
Хотя класс Pathname не так универсален в использовании как модуль FileUtils, класс Pathname может принести больше точности когда вам необходимы тяжелые обходы файловой системы. Pathname также ииспользуется в таких gem’ах как: Sprockets и Carrierwave.
Вы создаете объект типа Pathname просто передавая строку с путем файловой системы в конструктор класса. Вы также можете получить Pathname’ы через объединение двух путей используя Pathname.join или Pathname.+. Кроме того, многие методы класса Pathname возвращают объекты типа Pathname.
require "pathname" path = Pathname.new("/home/marcos/projects") #>> Pathname:"/home/marcos/projects" other = path.join("bragi") #>> Pathname:"/home/marcos/projects/bragi"
Объект типа Pathname может предоставлять большое количество информации о лежащев в его основе пути, например: путь к родительской директории, имя текущей директории, информацию о том является путь абсолютным или относительным, существует определенный файл или нет и т.д.
require "pathname" path = Pathname.new("/home/marcos/projects") path.dirname # Pathname: "/home/marcos/" path.basename # Pathname: "/home/marcos/projects" path.parent # Pathname: "/home/marcos/" path.file? # false path.absolute? # true path.relative? # false
Метод Pathname.ascend обходит все элементы по переданому пути и возвращает экземпляр Pathname для каждого из них. pathname.children возвращает массив со всеми директориями, что находятся в той же родительской директории, что и директория путь которой был передан, а метод Pathname.each_child позволяет пробежаться по этому списку.
require "pathname" path = Pathname.new("/home/marcos/projects") path.ascend { |x| puts x } #>> Pathname: "/home/marcos/projects" #>> Pathname: "/home/marcos/" #>> Pathname: "/home/" #>> Pathname: "/" path.each_child { |x| puts x } #>> Pathname: "/home/marcos/projects/bragi" #>> Pathname: "/home/marcos/projects/mimir" #>> Pathname: "/home/marcos/projects/guard-clone"
Pathname также предоставляет видимость для многих методов из классов File и Dir, позволяя вам в некоторых случаях писать более чистый код.
В Pathname существует один глюк — многие методы из Pathname, включая его конструктор, являются просто обертками для манипуляции строкой и без проблем будут принимать любую строку, которую вы передадите, однако некоторые методы, как, например, Pathname.children и Pathname.realpath выполняют запрос к файловой системе и будут возвращать ошибки если экземпляр Pathname не представлен в файловой системе (путь не верен, или отсутствует).
Оригинал статьи на английском: