2016-05-10 9 views
4

Я запускаю Perl в Windows, и я получаю список всех файлов в каталоге, используя readdir и сохраняя результат в массиве. Первые два элемента в массиве кажутся всегда «.» а также "..". Гарантирован ли этот заказ (если операционная система не изменяется)?Perl's 'readdir' Функция Result Order?

Я хотел бы сделать следующее, чтобы удалить эти значения:

my $directory = 'C:\\foo\\bar'; 

opendir my $directory_handle, $directory 
    or die "Could not open '$directory' for reading: $!\n"; 

my @files = readdir $directory_handle; 
splice (@files, 0, 2); # Remove the "." and ".." elements from the array 

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

+2

«Все решения, которые я видел, используют регулярные выражения или выражения для каждого элемента массива, и я бы предпочел не использовать ни один из этих подходов« Почему бы и нет? – ThisSuitIsBlackNot

+2

Вы должны понимать, что все найденные вами решения используют этот подход. Регулярное выражение, совпадающее с ведущим. также позволяет игнорировать файлы, имена которых начинаются с символа «.», который является стандартным способом сокрытия файлов в мире «nix». –

+0

@ RobK, я сделал. Вот почему я задавал этот вопрос в первую очередь. :) –

ответ

10

Гарантия не установлена ​​readdir. The docs state ...

Возвращает следующую запись в каталоге для каталога, открытого opendir.

Все дело в переходе записей в каталог в любом порядке, предоставленном файловой системой. Нет гарантии, что этот заказ может быть.

Обычный способ работы с этим состоит в равенстве регулярных выражений или строк.

my @dirs = grep { !/^\.{1,2}\z/ } readdir $dh; 

my @dirs = grep { $_ ne '.' && $_ ne '..' } readdir $dh; 

Поскольку это такая распространенная проблема, я бы рекомендовал использовать Path::Tiny->children вместо прокатки свой собственный. Они выяснят самый быстрый и безопасный способ сделать это, чтобы использовать grep для фильтрации . и ... Path :: Tiny многое исправляет в отношении обработки файлов и каталогов в Perl.

+0

Я рассмотрю Path :: Tiny-> children. Благодаря! –

+0

Если вы собираетесь использовать регулярное выражение, альтернатива, которую я считаю немного более читаемой, это '/^\.\.?$$'. –

+1

, у вас, по-видимому, нет файлов с именем «. \ N» или «.. \ n» :) '' 'действительно полезно для сопоставления ввода пользователя или файла; где-нибудь еще, избегайте этого – ysth

9

This perlmonks thread from 2001 исследовал этот самый вопрос, и мастер Perl Рэндал Шварц заключил

READDIR на Unix возвращает базовый сырец порядок каталогов. Дополнения и удаления в использование каталога и свободные слоты. Первые две записи в любой каталог всегда создаются как «точка» и «точка», и эти записи никогда не удаляются при нормальной работе.

Однако, если запись в каталоге для любого из этих файлов будет удалена некорректно (через повреждение или с использованием параметра perl -U и, например, отсоединиться от суперпользователя), следующий запуск fsck должен воссоздать запись и он просто добавит его. Ой, точка и точка не больше, чем первые две записи!

Таким образом, защитное программирование требует, чтобы вы не рассчитывали на порядок слотов. И нет обещаний, что точка и точка-точка являются первыми двумя записями, потому что Perl не может этого контролировать, и базовая ОС не обещает этого.

+0

Я боялся этого. –