2008-11-27 6 views
9

Всякий раз, когда я перечисляю содержимое каталога с помощью функции readdir, имена возвращаемых файлов также включают «.». а также "..". У меня есть подозрение, что это только обычные ссылки в файловой системе и поэтому неотличимы от реальных файлов, но мне всегда приходится их отфильтровывать, потому что они не являются фактическими объектами в каталоге, который я перечисляю. Есть ли веская причина для таких функций, как readdir, чтобы включить их? Некоторые операционные системы или файловые системы содержат больше или разных имен виртуальных файлов? Есть ли лучший способ отфильтровать их, кроме как путем сравнения строк с «.». а также ".."?Почему списки каталогов содержат текущий (.) И родительский (..) каталог?

Обновление: благодарю вас всех за ответ. Полагаю, я всегда думал, что такие вещи, как ./ и ../, были просто условностями, которые можно было бы решить путем поиска и замены. Я нахожу это немного удивительным, хотя, вероятно, более эффективным и прозрачным, чтобы они были частью самой файловой системы.

Один вопрос остается, однако: с. и .. произвольные имена для этих ссылок, существуют ли файловые системы, которые используют разные?

ответ

11

. и .. - это действительно жесткие ссылки в файловых системах. Они необходимы, чтобы вы могли указать относительные пути, основанные на некотором пути ссылки (рассмотрите "../sibling/file.txt"). Поскольку эти жесткие ссылки фактически существуют в файловой системе, имеет смысл для readdir рассказать вам о них. (на самом деле термин hard link просто означает некоторое имя, которое неотличимо от фактического каталога, на которое они ссылаются: оба они указывают на то же самое inode в файловой системе).

Лучший способ - это просто strcmp и игнорировать их, если вы не хотите их перечислить.

3

Одна из причин заключается в том, что без них нет способа добраться до родительского каталога. Или получить дескриптор текущего каталога.

Без них мы не можем делать такие вещи, как:

./run_this 

В самом деле, мы не могли бы добавить '' к $ PATH, что означает, что мы никогда не могли выполнять файлы, которые еще не были на пути.

+0

В Windows,. похоже, является частью PATH неявно, то есть вы можете просто ввести run_this. Будучи привыкшим к этому, я всегда считал, что префикс ./ немного раздражает при использовании Linux, хотя я понимаю его ценность для безопасности. – Lemming 2008-11-27 02:26:47

+0

Я не очень-то думал об ограничениях безопасности, пока это не объяснялось мне в начале этого года. У неприятного пользователя может быть команда в ее каталоге под названием ls, которую администратор может выполнять при навигации по этому каталогу, и эта команда может затем предоставить пользователю дополнительный доступ. Плохо. – 2008-12-11 03:04:52

1

Это обычные каталоги, они являются «жесткими ссылками» на текущий каталог и каталог выше. Они присутствуют во всех каталогах (даже на корневом уровне, где .. точно такой же, как .).

ls При использовании, вы можете отфильтровать . и .. с ls -A (обратите внимание на капитал -A).

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

touch .??* 

Примечание Этот шаблон также исключает любой другой файл, который начинается с точки и длиной только два символа (например, .x), но эти файлы редко.

При использовании программных файловых менеджеров, таких как readdir() Мне нужно исключить . и .. вручную. Так как эти два файла должны быть первым в списке, возвращаемой readdir() вы можете сделать это:

@files = readdir(DIR); 
for (1..2) { shift @files; } # get rid of . and .. 
# go on with your business 
+0

Эти две строки должны быть введены в функцию. – Svante 2008-11-27 02:16:19

+0

Откуда вы знаете, что они не * в * функции? :-) – 2008-11-27 02:19:08

0

Они сообщили, потому что они хранятся в списке каталогов. Так всегда работали унификации.

0

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

Нечто вроде grep { not /^.{1,2}\z/ } readdir HANDLE должно работать на вас.

-4

нет никакой веской причины, по которой сканирование каталогов должно возвращать эти имена файлов.

3

У меня есть подозрение, что это просто нормальные ссылки в файловой системе и поэтому неотличимы от реальных файлов

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

Когда вы вызываете readdir, вы получаете все места, в которые вы можете напрямую перейти с текущего узла. Если вы не хотите перечислять места, которые вы воспринимаете как «вверх», вы должны сами их отсортировать. Вы должны написать небольшую функцию для этого, возможно, называемую readdir_down. Я не знаю, в каком порядке readdir перечисляет каталоги, но, возможно, вы можете просто выбросить первые две записи.

) это в первом приближении, есть также «жесткие связи», которые делают дерево фактически сетью.

6

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

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

Смежные вопросы