Як Linux обробляє декілька послідовних роздільників шляхів (/ home //// ім'я користувача /// файл)?


111

Я працюю над сценарієм python, який передає місця розташування файлів у підпроцес scp. Це все добре, але я знаходжусь у ситуації, коли я можу в кінцевому рахунку об'єднати шлях з назвою файлу таким чином, що /на шляху є подвійний ' . Я знаю, що bash не має значення, якщо у вас є кілька роздільників файлів, але мені цікаво, як саме це виправлено. Це башти, які знімають зайві /або це ніколи не має значення?

Я прошу, тому що це врятує мені кілька рядків коду, щоб перевірити на додаткові /s під час об'єднання. Я знаю, що це не велика справа, але мені також цікаво. У мене є скрипт bash, який містить рядок cd //usr(замість cd /usr), який, мабуть, означає, що використання декількох /s у шляху може мати значення


7
Я б інвестував у додаткові рядки коду ...
Стефан,

5
Тільки в разі , якщо хто -то піклується, що я впевнений , що ніхто не робить, я насправді в кінцевому підсумку з допомогою пітона joinі abspathі такі команди.
Фальмарі

Відповіді:


165

Допускається декілька косої риски і рівнозначна одній косій косій рисі. З специфікації Single Unix (версія 3) , базове визначення §3.266 ім'я шляху : "Кілька послідовних косої риси вважаються такими ж, як одна коса риса".

Є один виняток: якщо ім'я шляху починається рівно з двох нахилів, воно може трактуватися по-різному (посилання: базові визначення § 4.11 роздільна здатність назви шляху ). Сам Linux цього не робить, хоча деякі програми та інші системи Unix-ish роблять (наприклад, Cygwin).

Трейлінг /в кінці імені шляху змушує шлях посилатися на каталог. У базових визначеннях ( POSIX 1003.1-2001 (Single Unix v3)) §4.11 роздільна здатність імені траєкторії , трейлінг /є еквівалентом трейлінгу /.. Основні визначення POSIX 1003.1-2008 (Single Unix v4) §4.12 знімає вимогу зробити його еквівалентним для того /., щоб щоб впоратися з неіснуючими каталогами (наприклад mkdir foo/, потрібна робота, тоді як mkdir foo/.не буде - див. обґрунтування змін).

Для програм, які діють на запис в каталозі, якщо fooце символічне посилання на каталог, то передача foo/- це спосіб зробити програмний акт в каталозі замість символічного посилання.

¹ Зауважте, що це стосується лише дозволу імені шляху, тобто для доступу до файлів. Маніпуляції з іменем файлів можуть працювати по-різному. Так , наприклад , basenameі dirnameігнорувати задні косу риску.


7
Еквівалент /.було видалено після подальшого обговорення, оскільки він був неоднозначним. У будь-якому разі +1 важко знайти таку інформацію, яка добре узагальнена.
хакре

17

Здається, ОС також не переймається цим, щойно спробувавши програму C з прямим syscall, щоб відкрити // зі шляху.

Ви можете використовувати функцію бібліотеки python os.path.normpath, щоб нормалізувати її, що дозволяє економити необхідність сканувати рядок, шукаючи додаткові дані. Інші мови мають подібні функції.

http://docs.python.org/library/os.path.html#os.path.normpath


5
Остерігайтеся наступного коментаря у джерелі нормпати: Нормалізуйте шлях, наприклад A // B, A /./ B і A / foo /../ B стають A / B. Слід розуміти, що це може змінити значення шляху, якщо воно містить символічні посилання!
Блюхорн

8

У всіх системах Unix, які я бачив, це те саме, що і в одній /, але стандарт Unix це визначає

Ім'я шляху, що починається з двох послідовних косих рис, може бути інтерпретоване визначеним реалізацією способом, хоча більше двох провідних косої риски слід розглядати як одну проділу.

тож оброблятись може спеціально, залежно від вашої системи. (Деякі старі версії Unix використовували подвійний провід /для віддаленого доступу до файлової системи, і все ще можуть бути деякі, що роблять.)


7
Cygwin (хоча це не справжній UNIX) справді перекладається //remote/...на віддалений доступ до файлової системи, можливо, для узгодження з Windows ' \\remote\....
ефемієнт

2
Я вважаю, (але не можу Google переглянути хороший довідник зараз), що API-версії сумісних програм для POS POS Windows також розглядаються так //remote/...само, як і \\remote\...формат шляху UNC .
Stephen P

1
Я думаю, що я пам'ятаю, що портативні імена Boost.Filesystem обробляють //особливим чином, щоб вони могли перевірити falseїх абсолютність, відповідність специфікації Unix / POSIX.

7

Використовуйте os.path.joinв Python, і ви не отримаєте декількох косої риски. Створення назви файлів самостійно за допомогою об'єднання рядків вважається поганим стилем Python.


Я погоджуюся, але ім'я файлу є частиною командного рядка, і замість розбору командного рядка для додавання до імені файлу (наприкінці) я просто хотів би додати його.
Фальмарі

1
@Falmarri: Ви не можете просто додати ім'я файлу до командного рядка! Командний рядок буде проаналізований оболонкою, тому спеціальні символи у іменах файлів потрібно цитувати. Отже, вам потрібно побудувати ім'я файлу, а потім його цитувати належним чином, щоб помістити його в командний рядок.
Жиль

Це дійсно конкретний проект, який я майже просто буду використовувати сам. Напевно, я не був достатньо чіткий, щоб виправдати, що я з цього приводу не був надійним. Я отримую цей рядок шляху до файлу з класу, який дає мені правильно прокладений шлях до файлу тощо. І я додаю його до аргументу командного рядка
Falmarri

1
@Falmarri: Тому використовуйте normpath, щоб очистити значення командного рядка, яким ви не керуєте, а потім використовуйте приєднати їх, щоб з'єднати їх.
Ніл Мейхью

Це власне те, що я закінчила робити = \ Я не могла впоратися з особливим випадком, коли мене просто дали /дуже добре.
Falmarri

3

Різниці немає.

Кілька косої риски ігноруються (без ефекту), наприклад:

ls -al //usr///////bin/sed

7
Там може бути , якщо це саме два , і на початку; Ім'я шляху, яке починається з двох послідовних косої риски, може бути інтерпретоване визначеним реалізацією способом . На практиці я думаю, що це правильно, і вони просто ігноруються
Michael Mrozek

Дякую Крис, я вдячний за уточнення! (на жаль, вхід на OpenID не працює для мене, або я б проголосував за вас)

@Rob Ви незареєстровані, але все одно ввійшли в систему (ви відстежуєте ваше cookie). Ви повинні мати змогу зареєструватися зараз, щоб підключити OpenID до свого облікового запису, але ви можете мати можливість голосувати будь-яким способом
Michael Mrozek

Дякую Майклу, але "ти маєш увійти або зареєструватися, щоб голосувати". Якщо ви використовуєте лише електронну адресу та ім’я, у вас немає повних привілеїв. А оскільки OpenID закінчується, і я не хочу створювати інший обліковий запис, мені не пощастило. Напевно, я винен у тому, що я лінивий, але ціную допомогу.

0

Звичайно, ви можете нормалізувати шлях з можливими множинними / (косими рисами) в ньому, пропустивши його через tr -s

NORMALIZED=$(echo "$UNHYGIENIC" | tr -s / /)

... а потім використовувати $NORMALIZED

Однак це повинно бути необхідним. Наскільки я знаю, будь-яке ядро ​​UNIX повинно ігнорувати паралельні роздільники шляху або концептуально трактувати їх як ... /./...


"повинен" -> "не повинен".
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.