W tej części będę dość często stosował określenie strumień danych, więc
wyjaśnię, co to znaczy. Strumień taki to pewien ciąg danych, który napływa do
programu podczas działania. Znaczy to, że nie wszystkie dane są dostępne z
początku, można odczytać tylko te, które już napłynęły. Reszta dochodzi w
czasie późniejszym.
Jednym z takich potoków jest standardowe wejście, czyli najczęściej
klawiatura. Ale nie zawsze chcesz sam wszystko wpisywać ręcznie, czasem
chciałbyś uruchamiać jakiś program, wpisać kilka poleceń, zapisać i wyjść
- ale dla sporej ilości plików. Wtedy możesz zapisać te parę poleceń w pliku
tekstowym i wczytywać ten plik tak, jakby był klawiaturą: program
parametry < plik-z-poleceniami. Ciężko mi wymyślić teraz jakiś
konkretny przykład, z resztą ta możliwość jest rzadko używana. Zapamiętaj, że
litery z takiego pliku będą traktowane, jakby były wpisane z klawiatury,
a cała operacja nazywa się przekierowaniem standardowego wejścia
(jednym z zastosowań jest rozpakowywanie plików poleceniem tar:
tar -x < archiwum.tar, które jest opisane szerzej w części
poświęconej pakowaniu)
Podobną operację możemy zrobić ze strumieniem danych wyjściowych, czyli tych,
które poszłyby na ekran. Wystarczy podać ls -l /etc >
zawartosc-katalogu-etc, zeby w pliku zawartosc-katalogu-etc
pojawiło się to, na co wskazuje nazwa pliku. Jeśli plik wcześniej istniał, to
zostanie nadpisany przez nowe dane. Jeśli chciałbyś dopisać nowe dane
na końcu tego pliku, lepiej użyj symbolu >> zamiast
>. Całość nazywa się przekierowaniem standardowego
wyjścia, w pełnej analogii do standardowego wejścia.
Jest jedna fajna sztuczka z wejściem i wyjściem, polegająca na przekierowaniu
wyjścia jednego programu na wejście innego. Takie ustrojstwo nazywa się
potokiem, a wykonuje w sposób następujący: ls -l /etc
| less. Ta pionowa kreska to znaczek [Shift+\], ls wypisuje
dane w formacie długim zawartość katalogu /etc, a less
te dane odczytuje i coś z nimi robi (konkretnie wyświetla z możliwością
przewijania). Uwaga: program less domyślnie nie występuje na
Solarisach, trzeba go osobno zainstalować; program more natomiast
jest w zasadzie na każdym un*xie, chociaż potrafi nieco mniej.
Takie cuda mogą służyć na przykład do innych ciekawych rzeczy: echo
"4*5/12" | bc -l wypisze na ekranie wynik działania. Polecenie
echo wypisuje na standardowe wyjście zadany parametr, natomiast
bc to kalkulator działający w linii poleceń (poczytaj manuala,
bc może ci się kiedyś przydać).
Teraz parę słów o standardowym wyjściu błędów, przeze mnie zwanym
standardowym błędem (standardowe wejście jest oznaczane przez
stdin, standardowe wyjście to stdout, a wyjście błędów to
stderr, co chyba nieźle uzasadnia skrót używany przeze mnie :-))
Programem, o którym wiem, że wypisuje tekst na standardowy błąd, jest
mpg321. Możesz go spokojnie użyć do testów.
Toto (standardowy błąd) nie jest przekierowywane przy zastosowaniu
znaczka >. Żeby przekierować standardowy błąd musisz podać
2> : program > redir-stdout 2> redir-stderr
przekieruje stdout do pliku redir-stdout, a stderr do
pliku redir-stderr. Jeśli chcesz zapisywać stdout
i stderr do tego samego pliku, to użycie najprostszego wyjścia może być
nieco niebezpieczne, bo może skasować dane zapisane przez jedno przekierowanie
(choć mogę się mylić i będzie działać poprawnie). Na pewno będzie działać
znaczek &>, który przekierowuje jednocześnie wyjście
i błąd.
Zauważ, że standardowy błąd nie jest przekierowywany przy puszczaniu
danych przez potok. Żeby tego dokonać trzeba użyć pewnego tricku: najpierw
przekierować stderr na stdout, a potem można użyć potoku.
Przekierowanie jednego wyjścia strumienia na inne wyjście odbywa się tak:
program 2>&1 (analogicznie program 1>&2
przekieruje stdout na stderr). Teraz można puścić całość przez
potok: program 2>&1 | less.
UWAGA: przekierowanie w stylu program 2>&1 > test puści
wyjście błędu na standardowe wyjście, a to, co poszłoby standardowym wyjściem
normalnie, zostanie zapisane do pliku. To znaczy błąd nie pójdzie do pliku,
tylko na ekran.
Dla wtajemniczonych: jedynka i dwójka w tych przekierowaniach to deskryptory
plików. Przy >& zamykany jest stary deskryptor, a nowy jest
duplikowany. Natomiast przesłanie potokiem wygląda, jakby szukało
standardowego wyjścia. Dlatego najpierw skopiowanie deksryptora, a potem
przesłanie potokiem całości przesyła również stderr, (program pisze do
tego samego strumienia i błędy, i komunikaty), a przekierowanie błędów
i wyjścia w różnych kolejnościach daje różne efekty końcowe.
Ciekawostka: można puścić potok kilka razy. Nie wiem, jak dokładnie to
wyjaśnić, może zademonstruję: ls -l /etc | grep rc.d | less wypisze
zawartość katalogu /etc, wyszuka linie z występującym
rc.d (za to odpowiada grep, opisany w następnej
części) i wypisze je z możliwością przewijania. Wyjście jednego programu
pójdzie na wejście drugiego, którego wyjście pójdzie na wejście trzeciego
programu. Można tak puszczać potoki wiele razy.