Правила синтаксиса пути

10

Я пишу библиотеку для манипулирования строками пути Unix. В таком случае мне нужно понять несколько неясных моментов синтаксиса, о которых большинство людей не будут беспокоиться.

Например, как лучше , как я могу сказать, это , кажется , что foo/barи foo//barкак указывают на то же место.

Кроме того, ~обычно обозначает домашний каталог пользователя, но что, если он появляется в середине пути? Что происходит потом?

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

(К сожалению, поиск таких терминов, как «Синтаксис пути Unix» просто приводит к миллиону страниц, обсуждающих $PATHпеременную ... Черт, я даже изо всех сил пытаюсь найти подходящие теги для этого вопроса!)

MathematicalOrchid
источник
Расширения ok ~ tilde и -filename лежат в основе определенных POSIX возможностей любой среды Unix. Несколько советов: имя файла может быть любым, кроме \ 0 или /. ////// и / это одно и то же. $ PWD обрабатывается в ядре и может быть прочитан для любого (Linux) процесса в / proc. /./ может встречаться только в корне пути. В $ PATH ::::: и: это одно и то же. / dev / null / dev / tty и / tmp являются POSIX-гарантированными путями для каждой совместимой системы.
mikeserv
1
Большая часть вашего вопроса (но не часть ~) посвящена тому, как linux обрабатывает несколько разделителей пути (/ home //// username /// file) . Ближе всего к нормативной справке будет спецификация POSIX или Single Unix - нелегкое чтение.
Жиль "ТАК - перестань быть злым"

Ответы:

13

Есть три типа путей:

  • относительные пути нравится foo, foo/bar, ../a, .. Они не начинаются с /и относятся к текущей директории процесса, выполняющего системный вызов с этим путем.
  • абсолютные пути, такие как /, /foo/barили ///x. Они начинаются с 1 или 3 или более /, они не являются относительными, ищутся, начиная с /корневого каталога.
  • POSIX позволяет //fooлечиться специально, но не указывает как. Некоторые системы используют это для особых случаев, таких как сетевые файлы . Это должно быть ровно 2 слеша.

За исключением начала, последовательности косых черт действуют как единое целое.

~является особенным только для оболочки , он расширяется оболочкой, он не является особенным для системы. То, как оно расширяется, зависит от оболочки. Оболочки выполняют другие формы расширений, такие как globbing ( *.txt) или расширение переменных /$foo/$barили другие. Что касается системы, то ~fooэто просто относительный путь, подобный _fooили foo.

Что нужно иметь в виду:

  • foo/это не то же самое, что foo. Это ближе к foo/.чем foo(особенно если fooэто символическая ссылка) для большинства системных вызовов на большинстве систем ( foo//то же самое, что и foo/если).
  • a/b/../cне обязательно совпадает с a/c(например, если a/bявляется символической ссылкой). Лучше не лечить ..специально.
  • это вообще безопасно считать a/././././bтаким же, как a/bесли бы.
Стефан Шазелас
источник
Так что в итоге, если я не забочусь о оболочке манипуляции пути (который является обширным и сложным), мне нужно только заботиться о /, .и ..(?)
MathematicalOrchid
Пример //fooобработки в Cygwin, где он используется для путей UNC . Это //server/share/dir/file.txtдопустимый путь, который по умолчанию указывает вне системы. Cygwin возвращается к локальной системе, если не может найти server.
Уоррен Янг
3

Например, насколько я могу судить, кажется, что foo / bar и foo // bar указывают на одно и то же место.

Да. Это часто встречается, потому что программное обеспечение иногда объединяет путь, предполагая, что первая часть не заканчивалась прямой косой чертой, поэтому добавляется одна, чтобы убедиться (это может означать, что их может быть два или более). foo///barа foo/////barтакже указать на то же место, что и foo/bar. Хорошая функция для библиотеки манипулирования путями - это та, которая уменьшает любое количество последовательных слешей до одного (кроме как в начале пути, где она может использоваться в виде URL-адреса, или, как указывает Стефан, для любого не указано специального назначения).

Кроме того, ~ обычно обозначает домашний каталог пользователя

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

Кроме того, он ~является допустимым символом в пути * nix и не должен быть изменен ни на что другое. В соответствии с этим , единственными символами, которые не являются допустимыми в имени файла Unix, являются /(потому что это разделитель пути) и «ноль» (или нулевой байт), потому что они вообще недопустимы в тексте.

лютик золотистый
источник
+1 за объяснение расширения тильды; Я понятия не имел, что вы могли бы сослаться на других пользователей с этим!
Математическая
2
Как говорит Стефан, вы не можете слепо свернуть все повторяющиеся косые черты. Многочисленные косые черты в начале пути должны быть тщательно обработаны.
Уоррен Янг
@WarrenYoung Отредактировано, чтобы прояснить это. PS. Вперед??! О_О
Златовласка
Лучше, хотя я бы не сказал, что это как-то связано с URL-адресами. UNC восходит к концу 1980-х годов, в то время как URL появились только спустя годы.
Уоррен Янг
@WarrenYoung Достаточно справедливо, хотя может показаться, что UNC специфичны для платформ MS , так //что технически это тоже не так. Как URL-адреса, так и более новые, в соответствии с SC, свободно неоднозначные спецификации POSIX для // могут быть получены из таких, и в этом случае «URL-ish» кажется подходящей меткой для соглашения (даже если UNCs старше, и даже если подобие непреднамеренно). Я бы никогда не сказал, что «они являются URL-адресами», только это //или \\ служит цели «URL-адреса».
Златовласка