Czy zmienna ścieżki katalogu powinna kończyć się końcowym ukośnikiem?

85

Czy definiując ścieżkę do katalogu jako zmienną lub stałą, należy ją kończyć końcowym ukośnikiem? Jaka jest konwencja?

pwdw Unixie pokazuje twój bieżący katalog bez końcowego ukośnika, podczas gdy tabulator cd /var/www/apps/zawiera końcowy ukośnik, co nie jest pewne.

meleyal
źródło

Odpowiedzi:

23

Nie dołączam końcowego ukośnika, gdy na przykład definiuję katalog do przechowywania plików. To dlatego, że będę go używać w podobny sposób

$store_file = "$store_path/$file_id";

Zawsze dodam ukośnik przed użyciem zmiennej, która ma przechowywać ścieżkę katalogu. Myślę, że lepiej jest zawsze dodać jeden, niż zastanawiać się, czy jest uwzględniony końcowy ukośnik.

Johan Soderberg
źródło
29
Brak końcowego ukośnika oznacza, że ​​nie jest jasne, czy ścieżka w $ store_path jest plikiem czy katalogiem. „/ tmp / store_data” czy to plik czy katalog?
Darwin,
4
Używając czegoś takiego jak funkcja realpath () PHP , nie wypisze końcowego ukośnika. Twój system i narzędzia mogą dyktować konwencję.
jmbertucci
10
Posiadanie wielu ukośników w dowolnym miejscu zazwyczaj będzie interpretowane jako pojedynczy ukośnik. Więc możesz nawet mieć coś takiego, '///' + $root + '//' + $file + '/'a to nie ma znaczenia. Chociaż posiadanie końcowego ukośnika jest dobrym sposobem na rozróżnienie, czy ścieżka jest plikiem lub katalogiem, lepiej byłoby dołączyć do ścieżek takich jak '/' + $rootzamiast, $root + '/'ponieważ nie można być pewnym, że dołączana ścieżka ma końcowy ukośnik , ale możesz mieć względną pewność, że wiele ukośników zostanie zinterpretowanych jako pojedynczy ukośnik w większości środowisk.
Xtrinity
3
@MatthewSlyman, Chodziło mi o to, że wszyscy spodziewają się, że /tmp/store_data/będzie to katalog, podczas gdy nie jest jasne, czym jest ta sama ścieżka bez traling slash/tmp/store_data
Darwin
6
Problem z tym jest następujący: jeśli zmienna nie istnieje, jest taka sama jak pusta, a rm -rf $foo/$barmoże kończyć się narm -rf /
12431234123412341234123
100

Idę z końcowym ukośnikiem, ponieważ:

  1. „Jeśli kończy się ukośnikiem, jest to katalog. Jeśli nie, to plik”. to łatwa do zapamiętania konwencja.

  2. Przynajmniej w systemach operacyjnych, z których często korzystam, podwojenie ukośnika nie powoduje żadnych problemów, a pominięcie ukośnika powoduje duże. Dlatego najbezpieczniej jest zarówno umieścić ukośnik w zmiennej, jak i użyć „$ path / $ file” podczas jej używania.

Dave Sherohman
źródło
9
Ścieżkę do katalogu można odróżnić od ścieżki do pliku tylko wtedy, gdy ścieżka katalogu zawiera ukośnik na końcu.
Darwin,
4
Wiele ukośników odpowiada jednemu ukośnikowi, chyba że ścieżka zaczyna się od podwójnego ukośnika. Zobacz unix.stackexchange.com/questions/1910/…
jdh8
4
Dodatkowo dodanie ukośnika na końcu zmiennej pozwala na dodanie „$ path / $ file” zamiast „$ path / $ file”, co pozwala na pustą $ path - czyli bieżący katalog roboczy. Ale nigdy nie używaj ukośnika odwrotnego zamiast ukośnika.
fantastyczny
Przydatne są też deskryptory plików
Francesco Gualazzi
@ jdh8 Nawet jeśli ścieżka zaczyna się od podwójnych ukośników, nadal powinna odpowiadać jednemu ukośnikowi. Chociaż może się to zmienić od wdrożenia do wdrożenia. Standardy unixowe stwierdzają, że A pathname that begins with two successive slashes may be interpreted in an implementation-defined manner, although more than two leading slashes shall be treated as a single slash.w większości przypadków zaobserwowano, że podwójne ukośniki są zwykle interpretowane jako pojedynczy ukośnik w typowych implementacjach.
Xtrinity
12

Wiem, że to ma 10 lat, ale chciałem dorzucić moje bardzo uparte 0,02 dolara.

Nie. Absolutnie nie.

Mówimy o systemie Unix. W odniesieniu do samego katalogu jest to węzeł jak każdy inny. Odnosząc się do katalogu, to nie powinien nigdy mieć Niecytowany ukośnik w nazwie (ref: dirname, pwd, ~, echo $HOME, echo $PATH, wyjście z lset al).

W przypadku oznaczania zawartości danego katalogu, następnie trzeba ukośnik. To znaczy, ls /home/karl/jest bardziej odpowiednie niż ls /home/karl(FTR, prawie zawsze robię to drugie, ponieważ ... cóż, leniwy).

Korzystając ze zmiennej zawierającej katalog do utworzenia pełnej ścieżki do pliku, zawsze należy spodziewać się umieszczenia ukośnika (tj., E:) cp ${HOME}/test ${OTHER_DIR}/.

Jest on oczekuje , że katalog nie kończy się ukośnikiem. Wszelkie oczekiwania, że ​​katalog kończy się ukośnikiem, są błędne. Zatem dodanie ukośnika na końcu wartości *_DIRzmiennej podważyłoby oczekiwania.

Jeśli chodzi o wypełnianie kart, oczekuje się, że przejdziesz do tego katalogu. Tak więc pomoc zapewniana przez wypełnianie kart polega na przeniesieniu Cię do tego katalogu, abyś mógł dokonać następnego wyboru na podstawie jego zawartości.

(odniesienie do komentarzy: Filepath Misconceptions , ze strony Wikipedii Talk:Path_(computing). Dzięki, john cj )

Warto zauważyć, że tylko dlatego, że jest źle, nie oznacza, że ​​narzędzia / pakiety / biblioteki nigdy tego nie robią. Jest to zbyt częste zdarzenie, że takie rzeczy dodają końcowy ukośnik, gdy żadna nie powinna istnieć. Dlatego, jak sugerowali Bevan i Paul F.

I-węzły systemu Unix

I-węzeł (węzeł indeksu) to struktura danych w systemie plików w stylu uniksowym, która opisuje obiekt systemu plików, taki jak plik lub katalog.

- https://en.wikipedia.org/wiki/Inode

Filesystem Hierarchy Standard

Standard dla systemu plików Unix (System plików Hierarchy Standard, AKA FHS) wyraźnie pokazują, że katalogi nie są traktowane jako posiadające ukośnik, ale zawartość katalogu rozpoczyna się ukośnikiem (jedyny wyjątek to /dlatego, że nie będzie odnosić się do katalog główny systemu plików, używając pustego ciągu ... i tak czy siak nie powinno się tam tworzyć plików.)

- http://www.pathname.com/fhs/pub/fhs-2.3.html

- https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard

Karl Wilbur
źródło
Doskonała odpowiedź. Zwykle stosowałem to podejście, ale nigdy nie byłem w pełni kompletny, jeśli chodzi o uzasadnienie. To jedyna odpowiedź, która go przydaje.
wardw
4
To korzeń /łamie schemat. A jeśli miałbyś zacząć swoje rozumowanie od tego miejsca (rekurencyjnie), możesz następnie dojść do sprzeczności, które mogą stanowić sedno rozbieżnych praktyk (czego dowodzą odpowiedzi tutaj). Ale kiedy zaakceptujesz to jako wyjątek, wszystko inne będzie zgodne.
wardw
Widzę. Trochę się bawiłem z dirname. Jeśli zamierzasz jawnie przechowywać katalog w ścieżce, zakończ ścieżkę znakiem „/.”, Gdzie kropka oznacza bieżący katalog.
TamusJRoyce
Nigdy byś nie skończył na a /., to po prostu okropny pomysł; Oprócz wstrzykiwania bardzo nietypowych treści, które powodują nieoczekiwane problemy, wygląda to po prostu głupio.
Karl Wilbur
2
@wardw można by pomyśleć o katalogu głównym jako o nazwie pustego łańcucha, podczas gdy „/” to pusty ciąg, po którym następuje ukośnik i oznacza „zawartość katalogu głównego”.
bobpaul
9

Tak, powinno, ponieważ:

Nazwa ścieżki + nazwa pliku = w pełni kwalifikowana lokalizacja pliku.

Zatem ukośnik między ostatnim katalogiem a nazwą pliku musi znajdować się na końcu ścieżki lub na początku nazwy pliku. Przedrostek nazw plików znakiem / oznacza, że ​​musisz wziąć to pod uwagę, jeśli chcesz tylko otworzyć plik (tj. Jeśli zakładasz, że niekwalifikowana nazwa pliku znajduje się w bieżącym katalogu roboczym).

PaulJWilliams
źródło
5
.. a nieuwzględnienie tego oznacza, że ​​prawdopodobnie nieumyślnie zadzierasz z /, i w ten sposób leży szaleństwo
JustJeff
5

Za każdym razem, gdy przechowuję ścieżki katalogów lub zwracam je z interfejsów API, staram się trzymać konwencji utrzymywania końcowego ukośnika. Pozwala to uniknąć całej niejednoznaczności „czy to plik czy katalog”.

Dodatek :
nie ma to zastępować stosowania metod, które mogą tolerować końcowy ukośnik lub jego brak. Nawet stosując tę ​​konwencję zawsze używam Path.Combine(...)i podobnych metod.

jerryjvl
źródło
python:os.path.join(dir, subdir_or_file)
IceArdor,
5

Może powinieneś pomyśleć o tym, co Twoja decyzja oznaczałaby dla plików. Jeśli nie dodasz ukośnika na końcu nazwy katalogu , będziesz musiał dodać go na początku nazwy pliku .

Teraz, jeśli z jakiegoś powodu brakuje ścieżki prowadzącej do pliku podczas łączenia ciągów, otrzymujesz coś takiego, /filenameco nie jest tylko plikiem, ale ścieżką bezwzględną z katalogu głównego (gdziekolwiek to może być w tym kontekście) .

Dlatego kończę moje ścieżki ukośnikiem i zachowuję pliki jako pliki.

DanMan
źródło
1
Alternatywą jest tutaj wyrażenie nazwy pliku jako ./filename. Ale generalnie to kod łączący ścieżki powinien odpowiadać za wykonanie tego poprawnie - i nie czynić żadnych założeń.
wardw
4

Wiem, że to stary wątek, ale pomyślałem, że podzielę się tym, co robię. Jeśli to możliwe, normalnie pozwoliłbym na oba i zrobiłbym coś takiego (jeśli to było PHP):

$fullPath = rtrim($directory, '/') . '/filename.txt');

W ten sposób, jeśli katalog jest zdefiniowany w pliku konfiguracyjnym, nie ma znaczenia, czy następna osoba, która go zmieni, będzie zawierała końcowy ukośnik, czy nie.

Paul F.
źródło
4

W php, ponieważ dirname (__ FILE __) funkcja zwraca nazwę katalogu bez ukośnika na końcu. Mam tendencję do trzymania się tej konwencji.

W przeciwnym razie użycie ukośnika na końcu nazwy katalogu spowoduje konflikt ze sposobem działania dirname (..), a następnie utkniesz z obsługą tych dwóch przypadków, ponieważ nie wiesz, czy nazwa katalogu pochodzi z katalogu (.. ) lub treść zdefiniowaną za pomocą końcowego ukośnika.

Podsumowanie: Nie używaj końcowego ukośnika, ponieważ dirname (..) tego nie robi.

// PHP Example
dirname(__FILE__); // returns c:\my\directory without a trailing slash, so stick to it!

W przypadku innych języków sprawdź funkcję, która wyodrębnia nazwę ścieżki i zobacz, czy używa końcowego ukośnika, czy nie, a następnie trzymaj się konwencji języka.

Basil Musa
źródło
2
Wyjątek: dirname ('/ test') = '/' - zamiast zwracać pusty ciąg, dirname zwraca w tym przypadku pojedynczy ukośnik! Zobacz notatki tutaj .
Matthew Slyman
3

Zwykle po prostu dodam końcowy ukośnik, ponieważ najprawdopodobniej zamierzam użyć tego katalogu do dodawania / pobierania plików ...

Jeśli chodzi o odwoływanie się do stron internetowych, może to faktycznie zwiększyć wydajność, pozostawiając końcowy ukośnik

http://www.netmechanic.com/news/vol4/load_no11.htm

James
źródło
2

Tak, jest wiele systemów plików, które obsługują pliki bez żadnych rozszerzeń, więc zawsze dodawaj końcowy ukośnik, aby uniknąć problemów.

maxp
źródło
1

I tak nigdy nie widziałem mocnej konwencji.

Jestem jednak całkiem pewien, że cokolwiek się zdecydujesz, ktoś inny będzie w 100% pewien, że powinno być inaczej. Dlatego najlepszym pomysłem jest tolerowanie tego, co jest ustawione w obie strony.

W świecie .NET Path.Combine () daje sposób na rozwiązanie tego problemu - istnieją odpowiedniki w innych środowiskach, od plików cmd w górę.

Bevan
źródło
1

Myślę, że jest to jeden z tych rzadkich przypadków, w których poprawna odpowiedź teoretyczna i praktyczna jest inna.

Wydaje się, że odpowiedź @Karl Wilbur jest z pewnością poprawna w sensie teoretycznym, ponieważ powinieneś być w stanie odróżnić odniesienie do samego węzła katalogu od zawartości katalogu.

Ale w praktyce będę twierdzić, że prawidłowa odpowiedź jest odwrotna:

  • Najważniejszym powodem jest to, że można z całą pewnością stwierdzić, że ścieżka /home/FSObjectX/jest folderem, podczas gdy /home/FSObjectXjest niejednoznaczna. Nikt nie może powiedzieć, czy jest to plik folderu.
    Specyfikacje powinny być zawsze dokładne i jednoznaczne, gdy tylko jest to możliwe.

  • W zdecydowanej większości przypadków zawsze będziesz odnosić się do zawartości folderu, a nie do samego węzła katalogu.
    W tych rzadkich przypadkach, gdy faktycznie to robisz, można to łatwo obsłużyć w kodzie, usuwając opcjonalny końcowy separator dir.

  • Używanie podwójnych separatorów dir nie zaszkodzi, chociaż na pewno brak jednego.
    Teoretycznie zły argument, ponieważ nie powinieneś kodować przez przypadek, ale w praktyce zdarzają się błędy i być może użycie końcowego katalogu dir-sep może skończyć się mniejszą liczbą błędów uruchomieniowych u użytkownika końcowego.

Czytając ten interesujący wątek, nie znalazłem żadnych wad używania trailing dir-sep, tylko że jest to błędne w sensie teoretycznym. A może coś przegapiłem?

MrCalvin
źródło
w praktyce okaże się, że właściwym oczekiwaniem nie jest zawieranie końcowego ukośnika. Wystarczy spojrzeć na każde używane narzędzie, które zostało napisane przez kompetentnych programistów.
Karl Wilbur