Dlaczego mkdir nie ma domyślnie ustawionej flagi -p, aby umożliwić tworzenie zagnieżdżonego katalogu?

11

Nie widzę powodu, dla którego -pflaga mkdirpowinna być domyślnie ustawiona.

  -p, --parents     no error if existing, make parent directories as needed

To, co widzę, jest nieniszczące. Czy przegapiłem coś ważnego w sposobie, w jaki to działa?

Po drugie, czy istnieje prosty sposób, aby ustawić to jako domyślne zachowanie mkdir?

Treffynnon
źródło
2
umieścić to w .bashrc: alias mkdir="mkdir -p".
Kevin
Po całej dyskusji zdecydowałem się na pseudonimmkdp
Treffynnon

Odpowiedzi:

6

Jest to opcjonalna funkcja, która nie zawsze jest pożądana - szczególnie w skryptach. W przypadku skryptów weź pod uwagę następujące wady:

  • Fakt, że katalog już istnieje, nie jest zgłaszany: jeśli skrypt ma umieścić niektóre pliki w nowo utworzonym katalogu, a ten katalog już istnieje i zawiera pliki, skrypt może sprawić wiele problemów. (Później będzie trudniej odfiltrować pliki, które zostały tam umieszczone przez skrypt).
  • Z drugiej strony, niektóre skrypty (lub ich części) mogą zależeć od wcześniej utworzonej struktury katalogów (być może przez inny pakiet / skrypt). Na przykład skrypt instalacyjny pakietu może wymagać umieszczenia bibliotek w podkatalogu /usr/local/lib/GreatSoftware/ImportantPartOfIt, ale biblioteki zależą od / link do rzeczy poniżej /usr/local/lib/GreatSoftware. Jeśli tego brakuje, skrypt nie powinien kontynuować.

Ogólne zachowanie mkdirsprawia, że ​​jest to łatwe i naturalne, ponieważ takie sytuacje są zgłaszane i można je od razu złapać.


Możesz utworzyć dla niego alias, jeśli chcesz zawsze używać mkdir -pw swoich powłokach:

alias mkdir='mkdir -p'

(To powinno przejść do twojej .bashrclub jakiejkolwiek konfiguracji używanej przez twoją powłokę.)

rozcietrzewiacz
źródło
1
Nie sugerowałbym aliasu standardowego polecenia, aby działało w niestandardowy sposób. To spowodowałoby, że skrypty nie byłyby przenośne i mogłyby dezorientować czytelników. alias mkdp="mkdir -p"Bardziej wskazane byłoby utworzenie nowego aliasu lub funkcji .
jlliagre
2
@jlliagre Nie, nie wpłynie to na skrypty. Aliasy zdefiniowane lokalnie w .bashrcnie (normalnie) wpływają na ich środowisko.
rozcietrzewiacz
Rzeczywiście, ale przegapiłeś mój punkt. Aliasing standardowego polecenia zmiany jego zachowania, nawet na własny użytek, nie jest zalecaną praktyką. Najgorszym przykładem jest wszechobecność alias rm='rm -i'.
jlliagre
1
@jlliagre Nie polecany przez kogo? ;) Ale tak, zgadzam się, wolałbym raczej użyć innego aliasu - ale ze względów praktycznych, a nie ideologicznych. Nie sądzę też, aby rm -ipseudonim był zawsze zły - choć może prowadzić do złych nawyków. Z pewnością nie wszystkie aliasy poleceń są równie dobre / złe - rozważ ls="ls --color=auto"lub ssh="TERM=xterm ssh"na przykład.
rozcietrzewiacz
W mojej rekomendacji nie ma nic ideologicznego. Alias ​​rm jest pośrednio odpowiedzialny za wiele utraconych plików (spotkałem wiele ofiar tego aliasu). Podejrzewałem, że mkdir ma, w znacznie mniejszym stopniu, niepożądane efekty uboczne. Oczywiście nie jestem przeciwny zmianom kosmetycznym, nie behawioralnym, takim jak przykłady ssh i ls.
jlliagre
16

Oczywiście można argumentować, że tworzenie katalogu nadrzędnego powinno być domyślnym i można użyć opcji sprawdzania, aby zapobiec tworzeniu katalogu, jeśli rodzic nie istnieje.

Ale powodem, dla którego jest odwrotnie, jest po prostu historia. Podstawowa wersja mkdir nie tworzyła katalogów nadrzędnych. Dlatego do dystrybucji X11 dołączono polecenie o nazwie mkdirhier, które było w stanie wykonać to zadanie: sprawdź, czy istnieją katalogi nadrzędne i utwórz je, jeśli to konieczne.

Później ta funkcjonalność została dodana do polecenia mkdir w wielu wersjach UNIX (nie wiem, czy obecnie jest w standardzie POSIX). Aby zachować zgodność ta funkcja została udostępniona przez włączanie flagą opcji: -p.

Dlaczego źle jest mieć domyślnie włączone? Skrypty mogą polegać na awarii mkdir, jeśli katalog macierzysty nie istnieje. Szczególnie jako root użytkownika tworzenie drzew katalogów może być niebezpieczne.

Przykład:

 if mkdir /backup/$(uname -n)/$(date +%Y%m%d)
  then
    perform_backup ...

W tym przykładzie katalog zostałby utworzony, a tworzenie kopii zapasowej nawet wtedy, gdy system plików /backupnie jest podłączony, a element nadrzędny /backup/$(uname -n)nie istnieje, jeśli domyślnie byłby odwrotnie.

Ogólna zasada: dobrą praktyką jest nie zmieniać domyślnego zachowania jakiegokolwiek narzędzia. W razie potrzeby podaj opcje umożliwiające zmianę domyślnego zachowania.

ktf
źródło
2
Podoba mi się przykład montowania, którego użyłeś tutaj. Nie myślałem o tym konkretnym scenariuszu.
Treffynnon
1
Opcje -p (i -m) zostały wprowadzone przez System V w 1983 roku. Oba są zdecydowanie częścią standardu POSIX.
jlliagre
4

Myślę, że to trochę filozofia. Polecenie bare mkdir (1) (bez opcji) reprezentuje wywołanie systemowe mkdir (2) , zapewniając jego funkcjonalność w powłoce, nie robiąc nic więcej.

ern0
źródło
4

Na początku było tylko gołe mkdirpolecenie. Zgodnie z zasadami projektowania Unixa to proste polecenie wykonało jedno proste zadanie: utworzenie katalogu.

Później mkdiruzyskano -popcję obsługi typowego przypadku użycia, w którym osoba dzwoniąca chce utworzyć zero, jeden lub więcej katalogów, aby zapewnić istnienie określonej ścieżki. Z kilku powodów nie stało się to operacją domyślną. Po pierwsze, nie wszystkie systemy miały tę bardziej złożoną funkcję, a wymaganie tej -popcji oznaczało, że skrypty, które go używały, otrzymywały rozsądny komunikat o błędzie (coś podobnego mkdir: invalid option -z), a nie dziwnie niekiedy tworzyły katalogi. Po drugie, a co najważniejsze, zachowanie mkdir -pnie jest kompatybilnym zamiennikiem mkdirwe wszystkich przypadkach.

W szczególności, w przypadku większości fileystems, mkdirto operacja atomowa . Jeśli program uruchomi się, mkdir playgrounda polecenie powiedzie się, program wie, że utworzył playgroundkatalog. Pozwala to programowi traktować nowy katalog jako jego wyłączny plac zabaw: jeśli równocześnie uruchomi się inna instancja tego samego programu, jego wywołanie do mkdir playgroundnie powiedzie się. Ta właściwość nie jest oczywiście zapewniona, mkdir -pponieważ pozwala na istnienie argumentu.

Gdyby mkdir -pistniał od samego początku, mógłby stać się trybem domyślnym, podobnie jak mkdir -apolecenie tworzenia pojedynczego katalogu. Ale to nie byłoby zgodne ze zwykłą filozofią projektowania Uniksa: większość podstawowych narzędzi to proste owijanie wokół podstawowych operacji podstawowych, a bardziej wyszukane zachowania (takie jak tworzenie wielu katalogów za jednym razem) wymagają wymyślnych opcji.

Gilles „SO- przestań być zły”
źródło
2

Dla mnie problemem jest to, że zachowanie opcji -p, gdyby była ona domyślna, jest zasadniczo efektem ubocznym. Dodaje złożoności polecenia, wykonując coś więcej niż to, o co go prosiłeś. Jest jeszcze jedna niewidzialna rzecz do zapamiętania. Jedną z podstawowych zasad prawidłowego programowania jest unikanie efektów ubocznych.

Współczesne języki programowania są tak potężne, że stosunkowo łatwo można zbudować dowolne złożone polecenie z prymitywów udostępnianych przez język. Wiąże się to z podjęciem świadomej decyzji o wymaganym zachowaniu, a także pozostawia konkretny, widoczny zapis tego, co zostało zrobione.

Joe
źródło