Ekran, klawiatura, inne takie

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.


Dalsza część kursu
Poprzednia część kursu
Jadłospis