Должен ли опендир Перла всегда возвращаться. и .. во-первых?

  opendir MYDIR, "$dir";
  my @FILES = readdir MYDIR;
  closedir MYDIR;

Похоже, что в 99,9% случаев первые две записи в массиве всегда «.» и "..". Более поздняя логика в сценарии имеет проблемы, если это не соответствует действительности. Я столкнулся со случаем, когда записи в каталоге появлялись позже. Это указывает на то, что файловая система повреждена или что-то еще? Есть ли известный порядок, в который возвращается опендир?


person ojblass    schedule 16.04.2010    source источник


Ответы (3)


Это всегда порядок операционной системы, представленный в несортированном сыром виде.

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

Следовательно, не следует просто «пропускать первые две записи». Вместо этого сопоставьте их явно, чтобы отклонить их.

person Randal Schwartz    schedule 16.04.2010
comment
Как именно они будут удалены? Можете ли вы описать одну из этих неестественных сцен? - person ojblass; 16.04.2010
comment
Я думаю, он имеет в виду, что что-то должно пойти не так, поскольку это обычно предотвращается. Если fsck исправляет это, для меня это означает повреждение. Я могу представить себе один случай, когда это могло произойти, когда родительский каталог был удален или утерян, а его содержимое не было (повреждение или неудачная операция). Если бы он был восстановлен в fsck, я полагаю, это привело бы к более позднему размещению .. в его подкаталогах. - person kbenson; 16.04.2010
comment
Существуют файловые системы, которые не хранят записи каталогов в упорядоченном списке и не возвращают . и .. в какой-либо конкретной позиции при нормальной работе. Например, ext3 / ext4 с включенными B-деревьями, который используется в самых последних версиях Linux. - person Gilles 'SO- stop being evil'; 13.09.2010

Порядок зависит от ОС и явно не определен.

Их достаточно легко отфильтровать.

   opendir MYDIR, "$dir";
   my @FILES = grep !/^\.\.?$/, readdir MYDIR  ;
   closedir MYDIR;
person Penfold    schedule 16.04.2010
comment
Я бы немного изменил ваше регулярное выражение для большей доступности: my @FILES = grep !/^[.]{1,2}$/, readdir MYDIR; - person DVK; 16.04.2010
comment
@DVK Мне нравится ^[.][.]?\z, но я такой странный. Просто убедитесь, что вы сделали якорь в конце строки, используя \z, а не $. - person Sinan Ünür; 16.04.2010
comment
Да ... помните, что /^\.\.?$/ также соответствует .. \ n, которое является допустимым именем, которое вы не хотите пропускать. - person Randal Schwartz; 17.04.2010

Используйте File :: Slurp :: read_dir, который по умолчанию возвращает список, который не включает . и ...

person Sinan Ünür    schedule 16.04.2010