Программирование на языке Ruby - [178]
• >ActiveDirectory
позволяет легко взаимодействовать с экземплярами Active Directory, работающими на серверах под управлением Microsoft Windows;
• >ruby-inifile
позволяет работать с ini-файлами (читать, разбирать и обновлять их).
В сети есть еще много библиотек, которые могут вам пригодиться. Ищите их на сайтах http://raa-ruby-lang.org и http://rubyforge.org.
14.8. Работа с файлами, каталогами и деревьями
При выполнении рутинных задач приходится много работать с файлами и каталогами, в том числе с целыми иерархиями каталогов. Немало материала на эту тему вошло в главу 4, но кое-какие важные моменты мы хотим осветить здесь.
Поскольку ввод/вывод — вещь системно-зависимая, то для различных систем приходится применять разные приемы. Если сомневаетесь, экспериментируйте!..
14.8.1. Несколько слов о текстовых фильтрах
Многие инструменты, которыми мы постоянно пользуемся (как поставляемые производителем, так и разрабатываемые собственными силами), — просто текстовые фильтры. Иными словами, они принимают на входе текст, каким-то образом преобразуют его и выводят. Классическими примерами текстовых фильтров в UNIX служат, в частности, программы >sed
и >tr
.
Иногда файл настолько мал, что целиком помещается в памяти. В этом случае возможны такие виды обработки, которые по-другому было бы сложно реализовать.
>file = File.open(filename)
>lines = file.readlines
># Какие-то операции...
>lines.each { |x| puts x }
Бывает, что нужно обрабатывать файл построчно.
>IO.foreach(filename) do |line|
> # Какие-то операции...
> puts line
>end
Наконец, не забывайте, что все имена файлов, указанные в командной строке, автоматически собираются в объект >ARGF
, представляющий конкатенацию всех выходных данных (см. раздел 14.2.2). Мы можем вызывать, к примеру, метод >ARGF.readlines
, как если бы >ARGF
был объектом класса >IO
. Вся выходная информация будет, как обычно, направлена на стандартный вывод.
14.8.2. Копирование дерева каталогов (с символическими ссылками)
Пусть нужно скопировать целое дерево каталогов в новое место. Сделать это можно по-разному, но если в дереве есть символические ссылки, задача усложняется.
В листинге 14.5 приведено рекурсивное решение. Оно достаточно дружелюбно — контролирует входные данные и выводит информацию о порядке запуска.
>require "fileutils"
>def recurse(src, dst)
> Dir.mkdir(dst)
> Dir.foreach(src) do |e|
> # Пропустить . и ..
> next if [".",".."].include? e
> fullname = src + "/" + e
> newname = fullname.sub(Regexp.new(Regexp.escape(src)),dst)
> if FileTest:rdirectory?(fullname)
> recurse(fullname,newname)
> elsif FileTest::symlink?(fullname)
> linkname = 'ls -l #{fullname}'.sub(/.* -> /,"").chomp
> newlink = linkname.dup
> n = newlink.index($oldname)
> next if n == nil
> n2 = n + $oldname.length - 1
> newlink[n..n2] = $newname
> newlink.sub!(/\/\//,"/")
> # newlink = linkname.sub(Regexp.new(Regexp.escape(src)),dst)
> File.symlink(newlink, newname)
> elsif FileTest::file?(fullname)
> FileUtils.copy(fullname, newname)
> else
> puts "??? : #{fullname}"
> end
> end
>end
># "Главная программа"
>if ARGV.size != 2
> puts "Usage: copytree oldname newname"
> exit
>end
>oldname = ARGV[0]
>newname = ARGV[1]
>if ! FileTest::directory?(oldname)
> puts "Ошибка: первый параметр должен быть именем существующего каталога."
> exit
>end
>if FileTest::exist? (newname)
> puts "Ошибка: #{newname} уже существует."
> exit
>end
>oldname = File.expand_path(oldname)
>newname = File.expand_path(newname)
>$оldname=oldname
>$newname=newname
>recurse(oldname, newname)
Возможно, и существуют варианты UNIX, в которых команда >cp -R
сохраняет символические ссылки, но нам о них ничего не известно. Программа, показанная в листинге 14.5, была написана для решения этой практической задачи.
14.8.3. Удаление файлов по времени модификации и другим критериям
Предположим, вы хотите удалить самые старые файлы из какого-то каталога. В нем могут, к примеру, храниться временные файлы, протоколы, кэш браузера и т.п.
Ниже представлена небольшая программа, удаляющая файлы, которые в последний раз модифицировались раньше указанного момента (заданного в виде объекта >Time
):
>def delete_older(dir, time)
> Dir.chdir(dir) do
> Dir.foreach(".") do |entry|
> # Каталоги не обрабатываются.
> next if File.stat(entry).directory?
> # Используем время модификации.
> if File.mtime(entry) < time
> File.unlink(entry)
> end
> end
> end
>end
>delete_older("/tmp",Time.local(2001,3,29,18,38,0))
Неплохо, но можно обобщить. Создадим метод >delete_if
, который принимает блок, возвращающий значение >true
или >false
. И будем удалять те и только те файлы, которые удовлетворяют заданному критерию.
>def delete_if(dir)
> Dir.chdir(dir) do
> Dir.foreach(".") do |entry|
> # Каталоги не обрабатываются.
> next if File.stat(entry).directory?
> if yield entry
> File.unlink(entry)
> end
> end
> end
>end
># Удалить файлы длиннее 3000 байтов.
>delete_if("/tmp") { |f| File.size(f) > 3000 }
># Удалить файлы с расширениями LOG и BAK.
>delete_if("/tmp") { |f| f =~ /(log|bak)$/i }
14.8.4. Вычисление свободного места на диске
Пусть нужно узнать, сколько байтов свободно на некотором устройстве. В следующем примере это делается по-простому, путем запуска системной утилиты:
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
Сейчас во многих школах, институтах и других учебных заведениях можно встретить компьютеры старого парка, уже отслужившие свое как морально, так и физически. На таких компьютерах можно изучать разве что Dos, что далеко от реалий сегодняшнего дня. К тому же у большинства, как правило, жесткий диск уже в нерабочем состоянии. Но и выбросить жалко, а новых никто не дает. Различные спонсоры, меценаты, бывает, подарят компьютер (один) и радуются, как дети. Спасибо, конечно, большое, но проблемы, как вы понимаете, этот компьютер в общем не решает, даже наоборот, усугубляет, работать на старых уже как-то не хочется, теперь просто есть с чем сравнивать.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
Python - объектно-ориентированный язык сверхвысокого уровня. Python, в отличии от Java, не требует исключительно объектной ориентированности, но классы в Python так просто изучить и так удобно использовать, что даже новые и неискушенные пользователи быстро переходят на ОО-подход.