Dlaczego `sort <„ $ f1 ”jest preferowany nad` sort - „$ f1” `i dlaczego jest to preferowane nad` sort '$ f1 ”?

29

Od /unix//a/458074/674

Pamiętaj, aby używać -- podczas przekazywania dowolnych argumentów do poleceń (lub przekierowań, jeśli to możliwe). Tak sort -- "$f1"lub lepiej sort < "$f1"zamiast sort "$f1".

Dlaczego warto używać --i przekierowywać?

Dlaczego jest sort < "$f1"preferowany sort -- "$f1"?

Dlaczego jest sort -- "$f1"preferowany sort "$f1"?

Dzięki.

Tim
źródło

Odpowiedzi:

55
sort "$f1"

kończy się niepowodzeniem dla wartości $f1rozpoczynających się od -lub tutaj w przypadku sortniektórych, które zaczynają się od +(może mieć poważne konsekwencje dla pliku wywoływanego -o/etc/passwdna przykład).

sort -- "$f1"

(gdzie -- sygnalizuje koniec opcji) rozwiązuje większość tych problemów, ale nadal nie działa w przypadku wywoływanego pliku -(co sortoznacza, że ​​oznacza to jego standardowe wejście).

sort < "$f1"

Nie ma tych problemów.

Tutaj jest powłoka, która otwiera plik. Oznacza to również, że jeśli pliku nie można otworzyć, pojawi się również potencjalnie bardziej przydatny komunikat o błędzie (na przykład większość powłok wskaże numer wiersza w skrypcie), a komunikat o błędzie będzie spójny, jeśli użyjesz przekierowania, tam gdzie to możliwe, do otwierania plików.

I w

sort < "$f1" > out

(w przeciwieństwie do sort -- "$f1" > out), jeśli "$f1"nie można go otworzyć, outnie zostanie utworzony / obcięty, a sortnawet nie uruchomiony.

Aby usunąć pewne możliwe nieporozumienia (następujące komentarze poniżej), nie uniemożliwia to komendzie mmap()wejścia do pliku lub lseek()wejścia do niego (nie tylko sortto), pod warunkiem, że sam plik jest widoczny. Jedyna różnica polega na tym, że plik jest otwierany wcześniej i na deskryptorze pliku 0 przez powłokę, w przeciwieństwie do późniejszej komendy na innym deskryptorze pliku. Polecenie może nadal szukać / mmap tego fd 0, jak mu się podoba. Nie należy tego mylić z cat file | cmdtym, że tym razem cmdstdin jest rurą, której nie można kształtować / szukać.

Stéphane Chazelas
źródło
4
Pamiętaj tylko, że użycie przekierowania zmusza sortdo sekwencyjnego odczytu danych, a mmappliku nie można . Chociaż sortmoże nie mieć z tym większych problemów, rozważ wydajność less <filei less file. W pierwszym przypadku lessmusi zachować całą zawartość pliku w pamięci, w drugim przypadku wolno odczytać tylko te części, które chce. Teraz wyobraź sobie, że fileto plik dziennika 100 GB ...
styropian leci
7
@styrofoamfly: To prawda, że less <fileprzechowuje cały plik w pamięci, ale nie jest do tego zmuszony, jest to wada mniej. Tylko cat file | lessjest zmuszony. Sprawdź less /dev/fd/0 <f, który nie przechowuje pliku w pamięci, nawet jeśli odbiera go na standardowym wejściu. Jest powszechnym błędnym przekonaniem, że stdin w Uniksie jest nie do zobaczenia. W rzeczywistości może być widoczny, w zależności od typu pliku.
pkt.
@styrofoamfly Czy masz na myśli to, że read()odczytujesz dane sekwencyjnie z pliku, jednocześnie mmap()odczytując cały plik do pamięci na raz?
Tim
1
@JohnBollinger Nie. To sięga co najmniej wstecz od getopt z SysIII w 1980 roku przed rozpoczęciem projektu GNU i musi być obsługiwane przez większość standardowych narzędzi, w tym sortprzez POSIX. Ale prawdą jest, że nie zawsze jest obsługiwana.
Stéphane Chazelas
2
Przepraszam, @ StéphaneChazelas, masz rację co do pochodzenia konwencji, a ponadto stwierdzę, że specyfikacja POSIX dla getopt()funkcji C rozpoznaje to znaczenie argumentu --. Ale główny punkt to ten, który akceptujesz: obsługa argumentów jest domeną poszczególnych programów i nie wszystkie traktują --specjalnie.
John Bollinger
17

Problemem są nazwy plików zaczynające się od myślnika. sort "$f1"nie działa, jeśli wartość f1zaczyna się od, -ponieważ polecenie zinterpretuje wartość jako opcję. Zwykle powoduje to błąd, ale może nawet spowodować lukę w zabezpieczeniach . Dzięki sort -- "$f1", argument podwójna kreska --oznacza „brak opcji poza ten punkt” Tak więc wielkość f1nie będą interpretowane jako opcja. Ale jest jeszcze jeden przypadek na krawędzi: jeśli wartością f1jest myślnik i nic więcej, to nie jest to opcja, to argument -, który oznacza „standardowe wejście” (ponieważ argument jest plikiem wejściowym; dla pliku wyjściowego oznaczałoby to „standardowe wyjście”).

Korzystanie z przekierowania pozwala uniknąć tych wszystkich pułapek.

Dotyczy to większości poleceń, nie tylko sort.

Gilles „SO- przestań być zły”
źródło
Czy mówisz, że sort < "$f1"to zadziałałoby, gdyby wartość była równa -? Nie ma go w żadnej skorupie, której próbowałem.
grawity
@grawity, porównaj seq 10 > -; sort -z seq 10 > -; sort < -.
Stéphane Chazelas