Все задачи

Созидательный труд

02 Sep 2013

В одном Очень Полезном Скрипте программисту понадобилось система вложенных каталогов: yyyy/mm/dd (год/месяц/день). Чтобы упростить их создание, программист написал модуль:

MkDir.pm (файл скачивается)

package MkDir;

use strict;
use warnings;

=head1 NAME

MkDir -- рекурсивное создание каталогов

=head1 SYNOPSIS

    use MkDir;
    MkDir::mkdir_recursive("test/a");
    MkDir::mkdir_recursive("/tmp/test/b");

=head1 DESCRIPTION

Модуль предоставляет функцию mkdir_recursive для рекурсивного создания каталогов.

Модуль предназначен для Unix-подобных систем с разделителем в именах каталогов "/" и корневым каталогом /.

=cut


sub mkdir_recursive
{
    my $path = shift or die "empty path, stop";

    my @parts = split "/", $path;

    my $dir = shift @parts || "/";
    mkdir $dir;
    for my $d (@parts){
        $dir .= "/$d";
        mkdir $dir;
    }
}

1;

Можно скачать пример использования.

Однако код, в котором использовался этот модуль, стал иногда выдавать сообщение print() on closed filehandle. Почему так?

Подсказка

Показать

Ошибка появляется, когда скрипту не хватает прав на создание каталогов.

Подсказка-2

Показать

Но при чем здесь может быть print() on closed filehandle ?

Разоблачение

Показать

Главная проблема в том, что результат выполнения mkdir не проверяется. Поэтому если создать каталог по какой-то причине не удалось, узнать об этом никак не получится.

Если же в якобы только что созданном каталоге попытаться открыть файл, не проверить результат open (как это происходит в примере кода), и попытаться что-то туда записать – возникает предупреждение о записи в неоткрытый дескриптор.

Мораль: всегда проверять результат mkdir, open, а для особо недоверчивых – и результат print.