Анимация
JavaScript


Главная  Библионтека 

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 [ 107 ] 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242

Переменные $saved size и $saved naii)e используются для хранения имени и размера самого большого файла. Если мы находим файл, размер которого превышает размер самого большого из просмотренного до настоящего момента, сохраненное имя и размер заменяются новыми значениями. После завершения работы find выводится имя и размер самого большого файла в весьма подробном виде. Вероятно, более практичная программа ограничится выводом имени файла, его размера или и того и другого. На этот раз мы воспользовались именованной функцией вместо анонимной, поскольку она получилась относительно большой.

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

use File::Find;

@ARGV = С .•) unless @ARGV;

my ($age, $name);

sub youngest {

return if defined $age && $age > -M;

Sage = (stat( ))[9];

$name = $File:;Find;;name;

find(\&youngest, @ARGV);

print "$name " . scalar(localtime($age)) , "\n";

Модуль File::Find не экспортирует имя переменной $name, поэтому на нее следует ссылаться но полному имени. Пример 9.2 демонстрирует скорее работу с пространствами имен, нежели рекурсивный перебор в каталогах. Он делает неременную $name текущего пакета синонимом неременной File::Find (в сущности, именно на этом основана работа модуля Exporter). Затем мы объявляем собственную версию find с прототипом, обеспечивающим более удобный вызов.

Пример 9.2. fdirs

#!/usr/bin/perl -Iw

# fdirs - поиск всех каталогов

@ARGV = qw(.) unless @ARGV;

use File::Find ();

sub find(&@) { &File:;Find:;find }

•name = *File::Find;:name;

find { print $name if -d } @ARGV;

Наша версия find вызывает File::Find, импортирование которой предотвращается включением пустого списка () в команду use. Вместо заниси вида:

find sub { print SFile::Find:;name if -d }, @ARGV;

можно написать более приятное

find { print $name if -d } @ARGV;

> Смотри также-

Man-страница find{\); рецепт 9.6; документация по стандартным модулям File::Find и Exporter.



9.8. Удаление каталога вместе с содержимым 339

9.8. Удаление каталога вместе с содержимым

Проблема

Требуется рекурсивно удалить ветвь дерева каталога без применения т -г.

Решение

Воспользуйтесь функцией f inddepth модуля File::Find (см. пример 9.3). Пример 9.3. rmtreel

#! /usr/bin/perl

# rmtreel - удаление ветви дерева каталогов (по аналогии с rm -г) use File;:Find qw(finddepth);

die "usage: $0 dir ..\n" unless (SARGV; •name = *File::Find::name; finddepth \&zap, (aARGV; sub zap {

if (!-l && -d ) {

print "rmdir $name\n";

rmdir($name) or warn "couldnt rmdir $name; $!"; > else {

print "unlink Sname";

unlink($name) or warn "couldnt unlink $name: $!";

Или воспользуйтесь функцией rmtree модуля File::Path (см. пример 9.4). Пример 9.4. rmtree2

#!/usr/bin/perl

# rmtree2 - удаление ветви дерева каталогов (по аналогии с rm -г) use File;;Path;

die "usage; $0 dir ..\n" unless (SARGV; foreach $dir (<aARGV) { rmtree($dir);

> Предупреждение--

Эти программы удаляют целые ветви дерева каталогов. Применяйте крайне осторожно!

Комментарий

Модуль Fi]e::Find экспортирует функцию find, которая перебирает содержимое каталога практически в случайном порядке следования файлов, и функцию finddepth, гарантирующую перебор всех внутренних файлов перед посещением самого каталога. Именно этот вариант поведения использован нами для удаления каталога вместе с содержимым.



У нас есть две функции, rmdir и unlink. Функция unlink удаляет только файлы, а rmdir - только пустые каталоги. Мы должны использовать finddepth, чтобы содержимое каталога заведомо удалялось раньше самого каталога.

Перед тем как проверять, является ли файл каталогом, необходимо узнать, не является ли он символической ссылкой, -d возвращает true и для каталога, и для символической ссылки на каталог. Функции stat, Istat и операторы проверки (типа -d) используют системную функцию stat(2), которая возвращает всю информацию о файле, хранящуюся в индексном узле. Эти функции и операторы сохраняют полученную информацию и позволяют выполнить дополнительные проверки того же файла с помощью специального манипулятора . При этом удается избежать лишних вызовов системных функций, возвращающих старую информацию и замедляющих работу программы.

> Смотри также-

Описание функций unlink, rmdir, Istat и stat вperlfunc{l); документация по стандартному модулю File::Find; шап-страницы ?-т(1) и stat{2); раздел рег/-func(l), посвященный операторам -X.

9.9. Переименование файлов

Проблема

Требуется переименовать файлы, входящие в некое множество.

Решение

Воспользуйтесь циклом foreach и функцией rename:

foreach $file (@NAMES) { my Inewname = $file; # change $file rename($file, $newname) or

warn "Couldnt rename $file to $newname: $!\n";

Комментарий

Программа вполне тривиальна. Функция rename получает два аргумента - старое и новое имя. Функция rename предоставляет интерфейс к системной функции переименования, которая обычно позволяет переименовывать файлы только в том случае, если старое и новое имена находятся в одной файловой системе.

После небольших изменений программа превращается в универсальный сценарий переименования вроде написанного Ларри Уоллом (см. пример 9.5).

Пример 9.5. rename

й/usr/bin/perl -W

# rename - переименование файлов от Ларри

$ор = shift or die "Usage: rename expr [files]\n";

chomp(@ARGV = <STDIN>) unless @ARGV:



0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 [ 107 ] 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242