Как стать автором
Поиск
Написать публикацию
Обновить

Две точки

Время на прочтение3 мин
Количество просмотров29K
скриншот консоли, который рвет шаблон

На картинке выше вы можете наблюдать, как ls считает, что linkylink/.. это не то же самое, что текущий каталог. При этом cd, кажется, с ним не согласен.

Начну рассказ со всем знакомых веб-адресов, которые похожи на системные пути.

Две точки в путях URI (в вебе)


Интерпретация точек описана в секции 5.2.4 RFC 3986.
Работает это так: каждый сегмент из двух точек уничтожает предыдущий сегмент:

/a/b/c/../../g <=> /a/g

при этом, если уничтожать нечего, две точки игнорируются:

example.com/../../../etc/passwd <=> example.com/etc/passwd

Правила были придуманы, чтобы относительные пути (../img/pic.png) можно было преобразовывать в абсолютные префиксом из uri-контекста:

  1. /a/css/index.css ссылается на ../img/pic.png
  2. в /a/css/index.css уничтожается все после последнего слеша => /a/css/
  3. ../img/pic.png прибавляется к /a/css/ => /a/css/../img/pic.png
  4. точки интерпретируются => /a/img/pic.png

Эти операции обычно делаются браузером, когда он преобразовывает относительные uri в абсолютные. Также, согласно стандарту, операция уничтожения точек должна выполняться при приведении uri к каноничному виду — нормализации — в том числе абсолютных uri.

Веб-сервера в дикой природе не сталкиваются с запросами содержащими точки и каждый обрабатывает их по-своему.

В целом, исходя из правила нормализации следует, что в uri вида 'http://example.com/a/b/../c' 'b' не обязана существовать.

Две точки в шелле


Схожим образом себя ведет шелловая команда cd: две точки всегда ведут на один сегмент путя выше, как бы отменяя предыдущий переход в подкаталог. Но, в отличие от uri, шелл проверяет существование промежуточных каталогов.

Если вы считаете первое естественным, то эта публикация для вас. На самом деле шелл эмулирует такое поведение cd: во всех остальных местах *nix ".." работает по-другому.


Даже встроенная команда source (или ее синоним ".") имеет отличное поведение от cd

Разница проявляется на символьных ссылках на каталоги: для cd переход по такой ссылке обратим через "..", тогда как остальная система будет воспринимать ".." как физического родителя каталога, на который ссылка указывает.

По-другому первое поведение называется logical (-L у pwd и cd), в противоположность physical (-P).

Две точки в файловой системе


В *nix ".." — это реальный подкаталог, единственный физический родитель, независимый от символьных ссылок. Если посмотреть внутрь файловой системы ext2, то описание подкаталогов ".." и "." ничем не будет отличаться от других, кроме того, что они перечисляются вначале.

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

Переход по некоторому пути — это то же самое, что последовательный переход в подкаталоги.

Нетрудно заметить, что если мы попали в некоторый каталог по символьной ссылке, то у нас не останется информации, чтобы вернуться: ".." будет указывать в физического родителя. Но как тогда cd работает с логическими путями, включающими в себя симлинки? Для этого шелл запоминает путь, по которому он пришел в каталог. Логический путь, построенный шеллом, доступен через переменную окружения $PWD или через pwd [-L].


Две точки требуют внимания, особенно в скриптах.

PS: Символьных ссылок на каталоги очень много в sysfs:

bug@earth /sys/class/net/lo % ls
addr_assign_type  flags              phys_port_id
address           gro_flush_timeout  phys_switch_id
addr_len          ifalias            power
...
bug@earth /sys/class/net/lo % ls ..
lo
bug@earth /sys/class/net/lo % pwd -P; pwd -L
/sys/devices/virtual/net/lo
/sys/class/net/lo
bug@earth /sys/class/net/lo % cd ..; ls
eth0  lo
Теги:
Хабы:
Всего голосов 33: ↑31 и ↓2+29
Комментарии18

Публикации

Ближайшие события