Jak Linux obsługuje wiele kolejnych separatorów ścieżek (plik / home //// nazwa użytkownika ///)?

111

Pracuję nad skryptem Pythona, który przekazuje lokalizacje plików do podprocesu SCP. W porządku, ale jestem w sytuacji, w której mogę skończyć konkatenację ścieżki z nazwą pliku, tak aby /na ścieżce było podwójne . Wiem, że bash nie ma znaczenia, jeśli masz wiele separatorów plików, ale zastanawiam się, jak dokładnie to naprawić. Czy to bash, który usuwa dodatkowe /s, czy naprawdę to nigdy nie ma znaczenia?

Pytam, ponieważ zaoszczędzi mi to kilka wierszy kodu, aby sprawdzić dodatkowe /s podczas konkatenacji. Wiem, że to nie jest wielka sprawa, ale jestem też ciekawa. Mam skrypt bash, który ma linię cd //usr(zamiast cd /usr), co sugeruje, że może istnieć znaczenie używania wielu /s na ścieżce

Falmarri
źródło
7
Zainwestowałbym w dodatkowe wiersze kodu ...
Stefan
5
Na wszelki wypadek ktoś dba, który jestem pewien, nikt nie robi, ja rzeczywiście kończy się przy użyciu Pythona joinoraz abspathi takich poleceń.
Falmarri

Odpowiedzi:

165

Dozwolonych jest wiele ukośników i są one równoważne jednemu ukośnikowi. Ze specyfikacją Single Unix (wersja 3) , definicje podstawowych §3.266 ścieżka „Wielokrotne ukośniki są uważane za tak samo jak jeden ukośnik”

Jest jeden wyjątek: jeśli nazwa ścieżki rozpoczyna się dokładnie dwoma ukośnikami, może być traktowana inaczej (patrz: definicje podstawowe §4.11 rozpoznawanie nazwy ścieżki ). Sam Linux tego nie robi, chociaż niektóre aplikacje mogą tak zrobić, a inny system unixowy (np. Cygwin).

Znak /końca na końcu ścieżki wymusza na ścieżce odniesienie do katalogu. W definicjach podstawowych ( POSIX 1003.1-2001 (Single Unix v3) §4.11 rozpoznawanie nazw ścieżek , trailing /jest równoważny trailingowi /.. POSIX 1003.1-2008 (Single Unix v4) definicje podstawowe §4.12 usuwa wymóg, aby był równoważny /., w celu radzić sobie z nieistniejącymi katalogami (np. mkdir foo/jest wymagany do pracy, podczas gdy mkdir foo/.nie - patrz uzasadnienie zmiany).

W przypadku programów, które działają na wpisie katalogu, jeśli foojest dowiązaniem symbolicznym do katalogu, wówczas przekazanie foo/jest sposobem, aby program działał na katalogu zamiast dowiązania symbolicznego.

¹ Pamiętaj, że dotyczy to tylko rozpoznawania nazw ścieżek, tj. Podczas uzyskiwania dostępu do plików. Manipulacje nazwami plików mogą działać inaczej. Na przykład basenamei dirnameignoruj ​​końcowe ukośniki.

Gilles
źródło
7
Odpowiednik /.został usunięty po późniejszym procesie dyskusji, ponieważ był niejednoznaczny. W każdym razie +1, ponieważ znalezienie tego rodzaju informacji dobrze podsumowanych jest trudne.
hakre
17

Wygląda na to, że system operacyjny też się tym nie przejmuje, ponieważ właśnie wypróbował program C z bezpośrednim wywołaniem syscall, aby otworzyć go // na ścieżce.

Możesz jednak użyć funkcji biblioteki python os.path.normpath, aby go znormalizować, co oszczędza ci konieczności skanowania ciągu w poszukiwaniu dodatków. Inne języki mają podobne funkcje.

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

Ivatar
źródło
5
Uważaj na następujący komentarz w źródle normpath: Normalizuj ścieżkę, np. A // B, A /./ B i A / foo /../ B stają się A / B. Należy rozumieć, że może to zmienić znaczenie ścieżki, jeśli zawiera ona dowiązania symboliczne!
Bluehorn,
8

Na wszystkich systemach Unix, które widziałem, jest taki sam jak jeden /, ale standard Unix to określa

Ścieżka rozpoczynająca się od dwóch kolejnych ukośników może być interpretowana w sposób zdefiniowany w implementacji, chociaż więcej niż dwa początkowe ukośniki należy traktować jako pojedynczy ukośnik.

więc może być obsługiwany specjalnie, w zależności od systemu. (Niektóre starsze wersje Uniksa używały podwójnego wiodącego /dostępu do zdalnego systemu plików, a niektóre nadal mogą to robić).

Fred Foo
źródło
7
Cygwin (choć nie jest prawdziwym systemem UNIX) tłumaczy //remote/...zdalny dostęp do systemu plików, prawdopodobnie w celu zachowania zgodności z systemem Windows \\remote\....
ephemient
2
Uważam (ale nie mogę teraz znaleźć w Google dobrej referencji), że interfejsy API kompatybilne z Windows POSIX będą również traktować //remote/...to samo, co \\remote\...format ścieżki UNC .
Stephen P
1
Wydaje mi się, że pamiętam, że przenośne nazwy ścieżek Boost.Filesystem działają //w specjalny sposób, ponieważ mogą sprawdzać, falseczy są absolutne, zgodne ze specyfikacją Unix / POSIX.
7

Użyj os.path.joinw Pythonie, a nie dostaniesz wielu ukośników. Samo budowanie nazw plików przez łączenie łańcuchów jest uważane za kiepski styl Pythona.

Neil Mayhew
źródło
Zgadzam się, ale nazwa pliku jest częścią ciągu polecenia i zamiast analizować ciąg polecenia, aby dołączyć go do nazwy pliku (na końcu), chciałbym go tylko dołączyć.
Falmarri,
1
@Falmarri: Nie możesz po prostu dołączyć nazwy pliku do ciągu poleceń! Łańcuch poleceń zostanie przeanalizowany przez powłokę, więc znaki specjalne w nazwach plików muszą być cytowane. Musisz więc skonstruować nazwę pliku, a następnie odpowiednio go zacytować, aby umieścić go w wierszu polecenia.
Gilles
To naprawdę specyficzny projekt, z którego sam zamierzam korzystać. Prawdopodobnie nie byłem wystarczająco jasny, aby uzasadnić brak solidności w tym zakresie. Otrzymuję ten ciąg ścieżki pliku z klasy, która daje mi poprawnie ścieżkę do pliku i tak dalej.
Dołączam
1
@Falmarri: Więc użyj normpath, aby wyczyścić wartość wiersza poleceń, której nie kontrolujesz, a następnie użyj join, aby je połączyć.
Neil Mayhew
Właśnie tak skończyłem = \ Nie mogłem poradzić sobie ze specjalnym przypadkiem, w którym dostałem /bardzo dobrze.
Falmarri,
3

Nie ma różnicy.

Wiele ukośników jest ignorowanych (bez efektu), np .:

ls -al //usr///////bin/sed
ChristopheD
źródło
7
Nie może być, jeśli jest to dokładnie dwa i na początku; Ścieżka rozpoczynająca się od dwóch kolejnych ukośników może być interpretowana w sposób zdefiniowany w implementacji . W praktyce myślę, że jest to słuszne i po prostu zostają zignorowani
Michał Mrożek
Dzięki Chris, doceniam wyjaśnienie! (niestety login OpenID nie działa dla mnie lub głosowałbym na ciebie)
@Rob Nie jesteś zarejestrowany, ale nadal jesteś zalogowany (jesteś śledzony przez swój plik cookie). Powinieneś być w stanie zarejestrować się teraz, aby podłączyć OpenID do swojego konta, ale musisz mieć możliwość głosowania w obu kierunkach
Michael Mrozek
Dzięki, Michael, ale „musisz się zalogować lub zarejestrować, aby głosować”. Gdy używasz tylko adresu e-mail i nazwy, nie masz pełnych uprawnień. A ponieważ upłynął limit czasu OpenID i nie chcę tworzyć kolejnego konta, nie mam szczęścia. Chyba moja wina za lenistwo, ale doceniam pomoc.
0

Oczywiście możesz znormalizować ścieżkę z możliwą wielokrotnością / (ukośników) w niej, przechodząc przez nią tr -s

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

... a następnie użyj $NORMALIZED

Jednak powinno to być konieczne. O ile wiem, każde poprawnie jądro UNIX powinno zignorować równoczesne separatory ścieżek --- lub koncepcyjnie traktować je jako /./...

Jim Dennis
źródło
„powinien” -> „nie powinien”.