Статьи

Рубин для новичков: работа с каталогами и файлами

Ruby — один из самых популярных языков, используемых в сети. Недавно мы начали новую сессию на Nettuts +, которая познакомит вас с Ruby, а также с отличными фреймворками и инструментами, которые сопровождают разработку на Ruby. Сегодня мы рассмотрим классы Dir и File и то, как мы можем использовать их для работы с каталогами и файлами.



Если вы проделали большую работу с терминалом (командная строка AKA, оболочка AKA), вы будете знать, что у него есть понятие текущего каталога, называемого рабочим каталогом. Это папка, в которой вы сейчас находитесь. Всякий раз, когда вы набираете команду, которая использует файл, рабочий каталог будет первым местом, где ваша оболочка ищет файл.

Ruby имеет аналогичное понятие при выполнении кода. Он понимает структуру папок ОС и имеет несколько полезных инструментов для работы с ней.

Итак, как узнать, в какой папке находится скрипт ruby?

1
Dir.pwd # «/Users/andrew/Documents»

Метод pwd (печать рабочего каталога) класса Dir предоставляет нам эту информацию. Если вы находитесь в irb , вашим рабочим каталогом будет — по умолчанию — папка, в которой вы запустили irb . Если вы находитесь в скрипте, это будет место, из которого вы вызываете скрипт.

Если вы хотите изменить рабочий каталог, вы можете использовать метод chdir ; передайте ему путь к каталогу, в который вы хотите перейти:

1
2
3
Dir.chdir «Documents»
 
Dir.chdir «/users/andrew/Documents»

Как видите, строковый параметр может быть как абсолютным, так и относительным путем.

Если вы ищете определенные файлы в рабочем каталоге ( Dir.pwd ), вы можете получить их, используя метод Dir.glob . Передайте этот метод «шар»; это шаблон поиска, который находится где-то между статической строкой и полным регулярным выражением. Вы можете использовать звездочку * в качестве подстановочного знака, как в командной оболочке; Вы можете использовать двойную звездочку ** для рекурсивного сопоставления каталогов. Вы также можете использовать наборы в квадратных скобках, как с регулярными выражениями. Если вам нужно больше, ознакомьтесь с полной документацией . Dir.glob с возвратом массива … или, вы можете передать ему блок и получить каждое совпадение по одному.

1
2
3
4
5
6
# Remember, this runs on the current directory
all_text_files = Dir.glob «*.txt»
 
Dir.glob(«**/*.[az]») do |filename|
    # will match any file in any child directory with a single lower-case letter extension
end

Помимо размещения полезных функций, вы также можете создать экземпляр класса Dir . Вы передаете ему имя каталога, который хотите использовать; как и для всех функций, которые принимают путь, он может быть абсолютным или относительным.

1
2
reciepts = Dir.new «reciepts»
me = Dir.open «/users/andrew»

И new и open возвращают объект Dir ; Тем не менее, есть еще один способ использовать open :

1
2
3
Dir.open «/users/andrew» do |dir|
    # use it here
end

Это общее соглашение со многими классами в Ruby; вместо того, чтобы хранить объект Dir в переменной, вы можете передать его в блок и использовать его оттуда. Это довольно другой стиль кодирования, которого я не видел ни на одном другом языке, но довольно приятно, только если вы привыкнете к нему.

Есть большая вероятность, что когда вы создадите объект Dir , вам захочется поработать с его содержимым. Есть несколько способов сделать это.

Предполагая, что some_dir является объектом Dir ,

1
2
3
some_dir.each do |file|
    # do something
end

Вы можете использовать each метод в объектах Dir для итерации по каждому файлу или каталогу, который находится внутри него. Обратите внимание, что вы не получаете объект File или Dir ; просто строка с названием этого; если вы хотите сделать больше, вам придется создавать соответствующий объект самостоятельно.

Если вы просто хотите увидеть, что находится внутри каталога, вы можете использовать свойство entries , чтобы получить массив содержимого:

1
some_dir.entries # [ «.», «..», «file_one.txt», «another_directory»]

Как вы заметите выше, в каталог для каталога входят «.» И «..», указатель на него и его родительский каталог.


Ruby также предлагает полезный API для работы с файлами.

Когда вы работаете с файлами, вы можете захотеть получить абсолютный путь к одному. Класс File предлагает именно то, что вам нужно:

1
File.absotule_path «plans.txt» # => «/users/andrew/Documents/plans.txt»

А как же наоборот? У вас есть абсолютный путь, и вы хотите просто имя файла? Вместо этого используйте basename

1
2
3
File.basename(«/users/andrew/Documents/plans.txt») # => «plans.txt»
 
File.basename(«/users/andrew/Documents/plans.txt», «.txt») # => «plans»

Если вы передадите второй строковый параметр, метод будет искать эту строку в конце имени файла и удалит ее, если она там есть; это не должно быть расширение файла, но это очевидное основное использование для этого.

Очевидное использование этого — удалить файл, который вы передаете в метод:

1
File.delete «code.rb»

Это полезный; Допустим, вы все работаете над записями объекта Dir , но вам нужны только файлы. File.directory? Метод вернет true если передаваемый ему строковый параметр является каталогом, и false если это файл.

1
2
3
4
5
Dir.open(Dir.pwd).each do |filename|
    next if File.directory?
 
    # otherwise, process file
end

Этот фрагмент open текущий каталог и передает блок each методу. each метод передает записи каталога по одной в блок. Эта первая строка внутри блока может немного смущать вас, если вы не привыкли к Ruby, но посмотрите на это внимательно. Единственная часть, с которой вы не знакомы, это ключевое слово next , которое пропускает оставшуюся часть блока и переходит к следующей его итерации. Итак, мы говорим: «переходите к следующей записи, если запись, которая у нас есть в данный момент, является каталогом. Если это не каталог, мы можем делать все, что захотим.

Создание экземпляров класса File работает так же, как и с Dir ; File.new возвращает объект File , тогда как File.open может вернуть его или передать в блок. Вы также должны передать второй параметр, который решает, как файл будет открыт. В большинстве случаев вы, вероятно, будете использовать это:

  • «R»: только для чтения
  • «W»: только для записи (перезаписывает что-либо в файле, если файл существует)
  • «W +»: чтение и запись (перезаписывает что-либо в файле, если файл существует)
  • «A»: только для записи (начинается в конце файла, если файл существует)

Итак, какие методы дает вам экземпляр File ? Ну, эти методы на самом деле происходят из класса IO , от которого наследуется File . В большинстве случаев вы будете открывать файл для чтения или записи содержимого, поэтому давайте рассмотрим эту функциональность.

Прежде чем начать, запомните следующее: как работает файл, после прочтения строки он больше не отображается; вы работаете с файлом. В любой момент вы можете использовать метод f.rewind чтобы вернуться к началу файла.

Если вы хотите просто прочитать все это, вы можете сделать это с помощью read .

1
2
3
f = File.open(«sample.txt», «r») # assume this file for the next couple of snippets
 
f.read # => «something\nline 2\na third\nfour!\n5555\nsixy\nsevenly\neight»

Тем не менее, вы, вероятно, захотите читать по одной строке за раз; Для этого используйте метод readline :

1
2
3
4
5
6
7
f.rewind # back at the beginning
 
f.readline # «something\n»
 
f.readline # «line 2\n»
 
f.readline # «a third\n»

Вы также можете использовать метод gets вместо readline .

Есть также метод readlines , который возвращает массив, в котором строки в виде записей:

1
2
3
f.rewind
 
f.readlines # => [«something\n», «line 2\n», «a third\n», «four!\n», «5555\n», «sixy\n», «sevenly\n», «eight»]

Наконец, вы можете использовать each и передать блок методу для работы с каждой строкой, одну за другой.

1
2
3
4
5
f.rewind
 
f.each do |line|
    puts line
end

Для записи у вас есть два варианта: write и puts . Основное отличие состоит в том, что puts добавляет разрыв строки в конец вашей строки, а write — нет.

1
2
3
4
5
6
7
8
9
f = File.open(«file.txt», «w+»)
 
f.puts «first line»
f.write «second «
f.write «line»
 
f.rewind
 
f.readlines # => [«first line\n», «second line»]

Ну, вот и все для Ruby For Newbies, урок 7. В классах Dir и File можно найти еще Dir -что; проверьте документы для Dir , File и IO для большего количества (класс IO — то, где File наследует его методы экземпляра).

Тем не менее, мне любопытно, откуда вы хотите, чтобы эта серия статей шла дальше: хотите ли вы продолжить работу с языком Ruby, или вы хотите перейти к использованию Ruby в Интернете? Оба направления будут ценны для вас, как для веб-разработчика, поэтому выскажите свое мнение в комментариях!