Użycie myślnika (-) zamiast nazwy pliku


110

W przypadku polecenia użycie -argumentu zamiast nazwy pliku oznacza STDIN lub STDOUT.

  1. Ale w tym przykładzie tworzy plik o nazwie -:

    echo hello > -

    Jak mogę zrobić -w tym przykładzie oznaczać STDOUT?

  2. I odwrotnie, jak mogę utworzyć -plik nazwany -w przykładach takich jak:

    cat -

3
Ponieważ najwyraźniej muszę mieć 50 reputacji, aby móc komentować bezpośrednio ... W komentarzu / dev / stdin / dev / stdout, AIX, który jest legalną pochodną UNIX, nie ma tych pseudourządzeń. Jako dalszy komentarz, LINUX w żadnym wypadku nie jest pochodną UNIX. Jest to wersja robocza zgodna z POSIX i najbardziej popularna w tym momencie z systemu operacyjnego UNIX, ale nie popełnijcie błędu, to nie jest UNIX. Ale treść odpowiedzi tutaj jest poprawna. Notacja „-” nie jest interpretowana przez powłokę jako specjalna i dlatego jest przekazywana bezpośrednio do każdej aplikacji jako ARG. Jeśli aplikacja nie

Istnieją również 2>&-konstrukcje, co oznacza „ścisły deskryptor 2”.
user3132194,

@ user95873, jak sądzę, chciałeś powiedzieć: chociaż Linux jest podobny do Uniksa, nie każdy z Uniksów (lub prawdziwy UNIX) jest Linuxem . Sprawa, czy Linux jest, czy nie jest prawdziwy UNIX (tj. Jest zgodny ze specyfikacją Single UNIX), nie ma związku z problemem / dev / std {in, out, err}. Ponieważ / dev / std {in, out, err} jest dodaną funkcją, której nie brakuje .
sasha

Odpowiedzi:


156

Użycie -jako nazwy pliku w celu oznaczenia stdin / stdout to konwencja używana przez wiele programów. To nie jest specjalna właściwość nazwy pliku. Jądro nie rozpoznaje -jako specjalnego, więc wszelkie wywołania systemowe określane -jako nazwa pliku będą używane -dosłownie jako nazwa pliku.

Z przekierowaniem bash -nie jest rozpoznawany jako specjalna nazwa pliku, więc bash użyje go jako dosłownej nazwy pliku.

Kiedy catwidzi ciąg -jako nazwę pliku, traktuje go jako synonim standardowego wejścia. Aby obejść ten problem, musisz zmienić ciąg, który catwidzi, tak aby nadal odwoływał się do pliku o nazwie -. Zwykle jest to poprzedzone nazwą pliku ścieżką - ./-lub /home/Tim/-. Technikę tę stosuje się również w celu obejścia podobnych problemów, w których opcje wiersza poleceń kolidują z nazwami plików, więc plik określany jako ./-enie pojawia się na przykład jako -eopcja wiersza polecenia programu.


37
Warto to dodać /dev/stdini /dev/stdoutsą one powszechnie dostępne i mogą być używane zamiast -konwencji.
jmtd

Również w tym catprzypadku użycie przekierowania zamiast wyświetlania argumentu może pomóc cat <-:; trudno byłoby jednak mieszać i łączyć to z łączeniem więcej niż jednego pliku na raz.
jmtd

10
@jmtd: / dev / std {in, out} nie są powszechnie dostępne. Nie wszystkie unixy mają to.
camh

2
Co ciekawe, założyłem, że były częścią POSIX (ale nie mogę potwierdzić). Są obecne przynajmniej w Linuksie, BSD i Solaris. Czy możesz podać przykład nowoczesnego systemu UNIX, który ich nie ma?
jmtd,

1
@camh Nie jestem pewien, czy otrzymałeś powiadomienie, a to jest bardzo, bardzo stary temat; Nie jestem pewien, czy możesz, ale jestem bardzo ciekawy, czy znasz odpowiedź na jmtdpytanie? :)
Obróć

18
  1. Zamiast tego echo hello > -możesz użyć echo hello > /dev/stdout.

    Chociaż „-” to konwencja, która musi zostać zaimplementowana przez każdy program, który chce go obsługiwać /dev/stdin, /dev/stdouti /dev/stderrjest obsługiwana przez system operacyjny (przynajmniej Solaris, Linux i BSD) niezależnie od aplikacji, a następnie będzie działała tak, jak Ty zamierzać.


9

Jak wspomniano camh , -to tylko konwencja nazewnictwa używana przez niektóre programy. Jeśli chcesz odwoływać się do tych strumieni za pomocą deskryptora pliku, który rozpozna powłoka, jiliagre miał rację , używając nazwy /dev/stdinlub /dev/stdoutzamiast niej. Te nazwy plików powinny działać w każdym miejscu, w którym działałaby normalna nazwa pliku.

  1. Biorąc to pod uwagę, twój pierwszy przykład jest trochę głupi. Wszelkie dane wyjściowe, które operator przekierowania przechwyciłby, aby zapisać do pliku, są już na standardowym wyjściu, więc przekierowanie go i zapisanie go tam, skąd pochodzi, jest bezużyteczne. Zachowanie, którego tam używasz, to potok, a nie przekierowanie:

    echo hello |
  2. W drugim przykładzie wystarczy podać, że można wskazać, że chcesz mieć plik literalny o tej nazwie, a nie jego wewnętrzny alias. Możesz to zrobić najłatwiej, określając ścieżkę do pliku w następujący sposób:

    cat ./-

6

Jeśli chodzi o 1, program musi go obsługiwać. Nie możesz po prostu arbitralnie z niego korzystać. Jeśli chodzi o 2, przekieruj dane wejściowe z (np cat < -.).


1

Podejście „-” ma wiele problemów. Przede wszystkim wymaga interpretacji znaku „-”, a wiele programów nie dokonuje takiej interpretacji. Ponadto istnieją programy, które interpretują łącznik jako ogranicznik oznaczający koniec opcji wiersza poleceń. Programy są napisane do pracy z argumentami nazw plików, podejście „-” to hack, ładne, ale słabe.

Najlepszym sposobem jest:

$ echo hello > /dev/fd/1

/dev/stdout to symbolik link do /dev/fd/1


Przekierowanie jest interpretowane przez powłokę, a nie wywoływany program.
sherrellbc
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.