Как Linux обрабатывает несколько последовательных разделителей пути (/ home //// username /// file)?

111

Я работаю над сценарием Python, который передает расположение файлов в подпроцесс scp. Это все нормально, но я нахожусь в ситуации, когда я могу конкатенировать путь с именем файла, так что в пути есть двойное /число. Я знаю, что bash не волнует, если у вас есть несколько разделителей файлов, но мне интересно, как именно это исправить. Это bash, который лишает лишних /s или это вообще не имеет значения?

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

Falmarri
источник
7
Я бы инвестировал в дополнительные строки кода ...
Стефан
5
Только в случае , если кто -то заботится, что я уверен , что никто не делает, я на самом деле в конечном итоге с помощью питона joinи abspathи такие команды.
Фальмарри

Ответы:

165

Допускается несколько косых черт, и они эквивалентны одной косой черте. Из спецификации Single Unix (версия 3) , базовые определения §3.266 pathname : «Несколько последовательных слешей считаются одинаковыми как один слеш».

Есть одно исключение: если имя пути начинается ровно с двух слэшей, оно может обрабатываться по-разному (см .: базовые определения §4.11 разрешение пути ). Сам Linux не делает этого, хотя некоторые приложения могут, а другие системы Unix-ish (например, Cygwin).

Завершающий /конец в конце имени пути заставляет имя пути ссылаться на каталог. В ( POSIX 1003.1-2001 определения (Single v3 Unix) базовых разрешениях имен путей §4.11 , замыкающий /эквивалентен завершающий /.. POSIX 1003.1-2008 (Single Unix v4) базовые определения §4.12 отменяет требование , чтобы сделать его эквивалент /., для того , справиться с несуществующими каталогами (например mkdir foo/, должен работать, а mkdir foo/.не будет - см. обоснование изменения).

Для программ, которые действуют на элемент каталога, если fooэто символическая ссылка на каталог, передача foo/является способом заставить программу действовать на каталог вместо символической ссылки.

¹ Обратите внимание, что это относится только к разрешению имени пути, то есть при доступе к файлам. Манипуляции с именами файлов могут работать по-разному. Например basenameи dirnameигнорировать косые черты.

жилль
источник
7
Эквивалент /.был удален после более позднего процесса обсуждения, поскольку он был неоднозначным. Во всяком случае, +1, так как найти такую ​​информацию хорошо обобщено сложно.
Хакре
17

ОС, похоже, тоже не заботится об этом, только что попробовав программу на C с прямым системным вызовом, чтобы открыть с // в пути.

Вы можете использовать библиотечную функцию python os.path.normpath, чтобы нормализовать ее, что избавляет вас от необходимости просматривать строку в поисках дополнений. Другие языки имеют аналогичные функции.

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

Ivatar
источник
5
Остерегайтесь следующего комментария в источнике normpath: нормализуйте путь, например, A // B, A /./ B и A / foo /../ B все станут A / B. Следует понимать, что это может изменить смысл пути, если он содержит символические ссылки!
Bluehorn
8

На всех Unix-системах, которые я видел, он такой же, как один /, но стандарт Unix указывает, что

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

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

Фред Фу
источник
7
Cygwin (хотя и не настоящий UNIX) действительно переводит //remote/...на удаленный доступ к файловой системе, вероятно, для согласованности с Windows \\remote\....
Эфимент
2
Я полагаю (но не могу найти хорошую ссылку прямо сейчас), что Windows POSIX compat API также будет обрабатывать //remote/...то же самое, что и \\remote\...формат пути UNC .
Стивен П
1
Мне кажется, я вспоминаю, что переносимые пути Boost.Filesystem обрабатываются //особым образом, поскольку они могут проверять falseабсолютность в соответствии со спецификацией Unix / POSIX.
7

Используйте os.path.joinв Python, и вы не получите несколько слешей. Создание имен файлов путем объединения строк считается плохим стилем Python.

Нил Мэйхью
источник
Я согласен, но имя файла является частью командной строки, и вместо разбора командной строки для добавления к имени файла (в конце) я просто хотел бы добавить его.
Фальмарри
1
@Falmarri: Вы не можете просто добавить имя файла в командную строку! Командная строка будет проанализирована оболочкой, поэтому специальные символы в именах файлов должны быть заключены в кавычки. Поэтому вам нужно создать имя файла, а затем заключить его в кавычки, чтобы поместить его в командную строку.
Жиль
Это действительно конкретный проект, который я собираюсь использовать сам. Я, вероятно, не был достаточно ясен, чтобы оправдать отсутствие уверенности в этом. Я получаю эту строку пути к файлу из класса, который дает мне правильно экранированный путь к файлу и тому подобное. И я добавляю это к аргументу командной строки
Фальмарри
1
@Falmarri: Поэтому используйте normpath, чтобы очистить значение командной строки, которое вы не контролируете, а затем используйте объединение, чтобы собрать их вместе.
Нил Мэйхью
Это на самом деле то, что я в итоге сделал = \ Я не мог справиться с особым случаем, когда мне просто дали /очень хорошо.
Фальмарри
3

Нет никакой разницы.

Несколько косых черт игнорируются (без эффекта), например:

ls -al //usr///////bin/sed
ChristopheD
источник
7
Там может быть , если это именно два , и в начале; Имя пути, начинающееся с двух последовательных слешей, может интерпретироваться способом, определяемым реализацией . На практике я думаю, что это правильно, и они просто игнорируются
Майкл Мрозек
Спасибо Крис, я ценю разъяснения! (к сожалению, у меня не работает логин OpenID, иначе я бы за вас проголосовал)
@Rob Вы не зарегистрированы, но все еще вошли (вы отслеживаете ваши куки). Вы должны быть в состоянии зарегистрироваться сейчас, чтобы подключить OpenID к вашей учетной записи, но вы должны иметь возможность голосовать в любом случае
Майкл Мрозек
Спасибо, Майкл, но "вы должны войти в систему или зарегистрироваться, чтобы голосовать". Когда вы используете только адрес электронной почты и имя, у вас нет полных прав. И поскольку OpenID истекает, и я не чувствую необходимости создавать другую учетную запись, мне не повезло. Думаю, я виновата в том, что ленилась, но я ценю помощь.
0

Конечно, вы можете нормализовать путь с возможными множественными / (косыми чертами), пропустив его через tr -s

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

... а затем использовать $NORMALIZED

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

Джим Деннис
источник
«должен» -> «не должен».