===== Wyświetlanie linków / tekstu / sekwencji liczb =====
==== Wyświetlanie zawartości plików ====
''**cat** [//plik//]...'' wyświetla podane //plik//i jeden po drugim (lub
wyświetla dane przeczytane ze standardowego wejścia jeśli nie podano //plik//u).
\\
Nazwa bierze się od operacji konkatenacji
\\
Z przełącznikiem ''-n'' program ''cat'' numeruje linie, a z ''-v'' wyświetla
bajty reprezentujące niedrukowalne znaki ASCII jako reprezentujący je tekst((Możesz sprawdzić jaki tekst odpowiada któremu bajtowi (poza ''\t'' i ''\n'', zastąpionym przez ''X''), wykonując: \\ ''perl -e'for(0..15){printf"\t%x_",$_};print"\n";for$l(0..15){printf"_%x",$l;for$h(0..15){$c=$h<<4|$l;$c=88 if $c==9||$c==10;printf("\t%c",$c)}print"\n"}'|cat -v'')).
''**paste** //plik_1// [//plik_2//]...'' czyta po jednej linii z każdego z plików
i wypisuje je oddzielone tabem, powtarzając to do wyczerpania najdłuższego pliku.
''**join** [-t //separator//] [-1 //filed_1//] [-2 //filed_2//] //infile_1// //infile_2//'' łączy te wiersze z pliku //infile_1// z wierszami pliku //infile_2//, które na polu //filed_1// w pliku //infile_1// mają tę samą wartość co na polu //field_2// w pliku //infile_2// (pola w wierszu są oddzielane //separator//em). Oba pliki muszą być posortowane względem pola które jest używane jako klucz połączenia.
''**fold** [-w //szer//] [//plik//]...'' wyświetla podane pliki (lub standardowe
wejście) wstawiając znak nowej linii kiedy tylko wypisywana linia miałaby być
dłuższa niż //szer// (domyślnie 80).
\\
''fold -s …'' wstawia nowe linie w miejsce ostatniej spacji przed //szer// (chyba
że nie ma ich w wierszu, wtedy wstawia je na //szer//-1).
''**column** [-x] [//plik//]...'' działa jak ''cat'' jeśli najdłuższa linia w
//plik//ach (bądź standardowym wejściu) nie zmieściłaby się dwukrotnie na szerokość
w terminalu;
w innym wypadku, wypisuje dane w tylu kolumnach ile mieści się na szerokość terminala,
uzupełniając wpierw kolumny (albo, z ''-x'', wiersze).
\\
''**column -t** [//plik//]...'' robi coś zupełnie innego: wykrywa kolumny w liniach
(rozdzielone separatorem, domyślnie białymi znakami) i formatuje //plik//i / wejście
w tabelę.
''**od** [-t x1] …'', ''**hexdump** [-C] …'', i ''**xxd** …'' pokazują pliki binarnie.
++++ Przykłady | {{page>so:redirects:cat&inline}} ++++
~~Zadanie.#~~ Wyświetl plik używając ''cat''. Wyświetl dwa pliki naraz używając ''cat''. \\
(Jeśli nie masz pomysłu jakie pliki wyświetlić, użyj np. ''/etc/SUSE-brand'' i ''/etc/os-release'')
~~Zadanie.#~~ Uruchom ''cat'', wpisz dowolny tekst, potem naciśnij //Enter// i //Ctrl+d//.
~~Zadanie.#~~ Wyświetl plik ''/usr/share/doc/mpich/user.pdf'' zarówno z przełącznikiem ''-v'' jak i bez niego.
~~Zadanie.#~~ Użyj ''paste'' do połączenia pliku z samym sobą.
~~Zadanie.#~~ Wyświetl plik ''/etc/mtab'' formatując go jako tabelę.
\\
Używając przełącznika ''-s'' do wybrania separatora wyświetl ''/etc/passwd'' formatując go jako tabelę.
~~Zadanie.#~~ Wyświetl binarny plik (np. ''/usr/share/themes/Breeze/assets/line-h.png'').
==== Wyświetlanie tekstu ====
''**echo** //tekst//'' wypisuje //tekst// i znak nowej linii. \\
Większość implementacji ''echo'' implementuje przełącznik ''-n'' który pomija
dodawnie znaku nowej linii.\\
Część implementacji zna też przełącznik ''-e'', który powoduje zamianę sekwencji
takich jak ''\t'' czy ''\n'' na odpowiadające im znaki (tutaj: tab i nowa linia).
Część implementacji zawsze zmienia sekwencje sterujące na odpowiadające im znaki
(i zgłasza błąd jeśli napotka przełącznik ''-e'').
''**printf** //format// [//argument//]...'' działa jak funkcja ''printf'' z języka C (z pewnymi dodatkami).
''**figlet** [//tekst//]'' wypisuje //tekst// (lub standardowe wejście) rysowane ascii-art'ową czcionką.
''**cowsay** [//tekst//]'' wyświetla krowę mówiącą //tekst// (lub standardowe wejście).
++++ Przykłady | {{page>so:redirects:echo&inline}} ++++
~~Zadanie.#~~ Sprawdź działanie ''echo -e 'foo\n\nbaz' '' \\ oraz ''echo -e '\n\n one \033[A \033[A two \033[B \033[B \n \033[1;31m red \033[0m' '' \\ [[https://en.wikipedia.org/wiki/ANSI_escape_code|Sekwencje sterujące ANSI]] są dobrze opisane [[https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797|tutaj]] oraz w podręczniku systemowym na stronie ''[[https://man7.org/linux/man-pages/man4/console_codes.4.html|console_codes]]''.
~~Zadanie.#~~ Sprawdź działanie ''printf "|%4.2f|%3s|%-16s|\n|%4.2f|%3s|%-16s|\n" 3.1428 pi obwod/srednica 9.8 g grawitacja''
==== Generowanie sekwencji liczb ====
''**seq** [//start// [//krok//]] //granica//'' generuje sekwencje liczb zaczynające się od //start//, zwiększanego o //krok// dopóki nie zostanie przekroczona //granica//.
\\
Jeśli nie podano, //start// i //krok// mają wartość 1.
\\
Opcja ''-w'' dopisuje taką ilość zer, by liczby miały tyle samo znaków (np. ''seq -w 8 11'' wypisze 08, 09, 10 i 11).
++++ Przykłady | {{page>so:redirects:seq&inline}} ++++
~~Zadanie.#~~ Wygeneruj sekwencję liczb od 1 do 15.
~~Zadanie.#~~ Wygeneruj sekwencję liczb od 64 do 1024 z krokiem co 64.
===== Standardowe strumienie =====
| K&R C[[https://archive.org/details/TheCProgrammingLanguageFirstEdition|[1]]] [[https://en.wikipedia.org/wiki/C_(programming_language)#K&R_C|[2]]]printf("Wpisz swoje imię:\n")
scanf("%s", name);
| Pythonprint("Wpisz swoje imię:")
name = input()
|
Czy zastanawiałeś się skąd program wie skąd czytać dane wejściowe i gdzie
funkcje takie jak print powinny wypisywać?
**W "uniksowym" świecie program oczekuje że w momencie uruchomienia będzie
mieć otwarte trzy pliki – standardowe wejście, standardowe wyjście i standardowy
błąd. (Które razem są nazywane [[https://en.wikipedia.org/wiki/Standard_streams|standardowymi strumieniami]].)**
\\
Bazuje na tym standardowa biblioteka wejścia/wyjścia z języka C – ''stdio.h''.
C zostało stworzone przez jednego z autorów UNIXa.
W większości języków programowania podstawowe funkcje I/O czytają ze
standardowego wejścia i piszą do standardowego wyjścia. \\
Standardowy błąd w założeniu ma służyć do raportowania co poszło nie tak.
Języki programowania często mają dedykowane funkcje piszące do tego strumienia.
W uniksopodobnych jak i kompatybilnych z POSIX-em systemach system operacyjny
zajmuje się faktyczną realizacją dostępu do pliku, a użytkownik tylko zleca
jakie operacje mają być wykonane. Otwierając plik użytkownikowi zwracany jest
jego identyfikator – **deskryptor pliku** – liczba całkowita będąca w
rzeczywistości indeksem w odpowiedniej tablicy systemu operacyjnego.
\\
Zlecając operacje take jak np. odczyt danych, użytkownik podaje ten numer,
rodzaj operacji i jej szczegóły, np. dla odczytu podaje ile bajtów odczytać
i gdzie umieścić odczytane bajty.
Proces potomny dziedziczy wszystkie deskryptory rodzica.
**Trzy standardowe strumienie to pliki wskazywane przez trzy pierwsze deskryptory:
\\
0 jest zawsze standardowym wejściem, 1 wyjściem, a 2 błędem.**
W uniksopodobnych systemach "plik" niekoniecznie jest danymi na dysku, system
UNIX próbował [[https://en.wikipedia.org/wiki/Everything_is_a_file|wszystko]]
reprezentować jako pliki.
Na przykład, dla systemu terminal jest plikiem (nawet jeśli jest podłączoną do
komputera maszyną do pisania).
Domyślnie powłoki mają otwarty terminal jako pliki 0, 1 i 2.
===== Przekierowania =====
Zgodne z POSIX-em powłoki potrafią zastąpić standardowe strumienie wskazanymi
przez użytkownika.
==== Często używane przekierowania ====
=== Przekierowanie wyjścia ===
''komenda **>** nazwa_pliku''
- otwiera plik //nazwa_pliku// do zapisu,
- ucina plik (= ustawia rozmiar pliku na 0, zawartość pliku jest tracona),
- zastępuje standardowe wyjście plikiem.
''komenda **2>** nazwa_pliku''
- otwiera plik //nazwa_pliku// do zapisu,
- ucina plik (= ustawia rozmiar pliku na 0, zawartość pliku jest tracona),
- zastępuje standardowy błąd plikiem.
''komenda **&>** nazwa_pliku'' Uwaga: to jest rozszerzenie powłoki Bash
- otwiera plik //nazwa_pliku// do zapisu,
- ucina plik (= ustawia rozmiar pliku na 0, zawartość pliku jest tracona),
- zastępuje standardowe wyjście i standardowy błąd plikiem.
''komenda **>>** nazwa_pliku''
- otwiera plik //nazwa_pliku// w trybie dopisywania (tzn. tryb zapisu w którym pozycja ustawiona jest na koniec pliku),
- zastępuje standardowe wyjście plikiem.
**''/dev/null''** jest urządzeniem które zaakceptuje każdy zapis i zignoruje przekazane dane ("czarna dziura").
++++ Przykłady | {{page>so:redirects:out&inline}} ++++
~~Zadanie.#~~ Komenda ''date'' wypisuje bieżącą datę. Przekieruj jej wynik do pliku.
~~Zadanie.#~~ Dodaj kolejną datę do pliku z poprzedniego zadania.
~~Zadanie.#~~ Wykonaj komendę ''cat /etc/motd /etc/shadow''. Przekieruj jej standardowy błąd do pliku.
~~Zadanie.#~~ Wykonaj ''find /var/spool/'' (polecenie ''find'' będzie omawiane później). Przekieruj standardowy błąd do pliku ''/dev/null''.
~~Zadanie.#~~ Przekieruj standardowe wyjście komendy ''find /var/spool/'' do jednego pliku, a standardowy błąd do innego.
~~Zadanie.#~~ Przekieruj standardowe wyjście i standardowy błąd komendy ''find /var/spool/'' do tego samego pliku.
=== Przekierowanie wejścia ===
''komenda < nazwa_pliku''
- otwiera plik //nazwa_pliku// do odczytu,
- zastępuje standardowe wejście plikiem.
''komenda << ogranicznik'' (here document)
- przed uruchomieniem //komenda//, powłoka tworzy tymczasowy plik,
- powłoka czyta dane ze swojego standardowego wejścia linia po linii i wpisuje te linie do tymczasowego pliku,
- do momentu aż linia będzie składać się tylko z //ogranicznik//a,
- otwiera tymczasowy plik do odczytu,
- zastępuje standardowe wejście plikiem.
''komenda <<< tekst'' (here string) Uwaga: to jest rozszerzenie powłoki Bash
- tworzy tymczasowy plik wpisując do niego //tekst// i znak nowej linii,
- otwiera tymczasowy plik do odczytu,
- zastępuje standardowe wejście plikiem.
++++ Przykłady | {{page>so:redirects:in&inline}} ++++
~~Zadanie.#~~ Stwórz plik zawierający ''print("hello " + __file__)''. Uruchom komendę ''python'', kolejno: podając plik jako argument, i przekierowując plik jako standardowe wejście.
~~Zadanie.#~~ Użyj programu ''hexdump -C'' do wyświetlenia dowolnego tekstu wpisanego jako //here document//. \\ Użyj w tekście wielobajtowego znaku (np. '''Witaj świecie!''' zawiera dwubajtowy znak ''ś'').
~~Zadanie.#~~ ''bc'' jest prostym kalkulatorem. Użyj go żeby policzyć ''sqrt(2.0000)''.
\\
Potem policz ''sqrt(2.0000)'' w nieinteraktywnym trybie.
~~Zadanie.#~~ Użyj ''bc'' do policzenia ''sqrt(2.0000)'' w nieinteraktywnym trybie i przekieruj wynik do pliku.
==== Szczegóły ====
[[https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_07|Rozdział o przekierowaniach w standardzie POSIX]] \\
[[https://www.gnu.org/software/bash/manual/html_node/Redirections.html|Dokumentacja Basha o przekierowaniach]]
Każde przekierowanie ma postać: **''[//deskryptor_pliku//]//operator// //słowo//''**
**Domyślny //deskryptor_pliku// to 0 jeśli //operator// zawiera ''<'' albo 1 w przeciwnym wypadku**
\\
Czyli: ''komenda < plik'' jest identyczna z ''komenda 0< plik'', a ''komenda >> plik'' jest identyczna z ''komenda 1>> plik''.
\\
Standard POSIX wymaga by deskryptory od 0 do 9 były do dyspozycji użytkownika.
To jak można wykorzystywać inne numery zależy od użytej powłoki.
Dostępne //operator//y to:
| ''<'' | otwiera plik //słowo// do odczytu i zastępuje //deskryptor_pliku// nowo otwartym|
| ''>'' | wyświetla błąd jeśli plik //słowo// istnieje i opcja "noclobber" jest ustawiona((Opcja "noclobber" jest domyślnie wyłączona; można ją włączyć komendą ''set -C''.)),\\ otwiera plik //słowo// do zapisu, ucina go i zastępuje //deskryptor_pliku// nowo otwartym plikiem |
| ''>|'' | otwiera plik //słowo// do zapisu, ucina go i zastępuje //deskryptor_pliku// nowo otwartym plikiem \\ (niezależnie czy plik //słowo// istnieje) |
| ''>>'' | otwiera plik //słowo// do dopisywania i zastępuje //deskryptor_pliku// nowo otwartym |
| ''<>'' | otwiera plik //słowo// do odczytu i zapisu, oraz zastępuje //deskryptor_pliku// nowo otwartym |
| ''<<'' | 1) tworzy tymczasowy plik \\ 2) czyta linię ze standardowego wejścia\\ 3) jeśli cała linia to dokładnie //słowo//, idź do 7 \\ 4) jeśli //słowo// nie było ujęte w cudzysłowy (pary ''"'' lub '
), wykonuje podstawienia((Np. pod ''$VAR'' podstawia wartość zmiennej ''VAR'', ''`date`'' jest zastąpione wynikiem komendy ''date'' etc.)) w linii \\ 5) pisze linię do pliku tymczasowego \\ 6) wraca do 2 \\ 7) otwiera plik tymczasowy do odczytu \\ 8) zastępuje //deskryptor_pliku// nowo otwartym \\ 9) uruchamia komendę |
| ''<<-''| działa jak ''<<'', ale po kroku 2 dodaje jeszcze krok: \\ 2a) usuwa wszystkie początkowe tabulatory (''\t'') \\ uwaga: spacje nie są usuwane|
| ''<<<''| Uwaga: to jest rozszerzenie powłoki Bash \\ 1) tworzy tymczasowy plik \\ 2) pisze //słowo// do pliku tymczasowego \\ 3) pisze znak nowego wiersza do pliku tymczasowego \\ 4) otwiera plik tymczasowy do odczytu \\ 5) zastępuje //deskryptor_pliku// nowo otwartym \\ 6) uruchamia komendę |
| ''<&'' | jeśli //słowo// jest deskryptorem pliku //p// otwartym w trybie pozwalającym na odczyt: duplikuje deskryptor //p// tak żeby zarówno //słowo// jak i //deskryptor_pliku// odnosiły się do tego samego \\ jeśli //słowo// jest ''-'': zamyka //deskryptor_pliku// |
| ''>&'' | jeśli //słowo// jest deskryptorem pliku //p// otwartym w trybie pozwalającym na zapis: duplikuje deskryptor //p// tak żeby zarówno //słowo// jak i //deskryptor_pliku// odnosiły się do tego samego \\ jeśli //słowo// jest ''-'': zamyka //deskryptor_pliku// |
| ''&>'' | Uwaga: to jest rozszerzenie powłoki Bash \\ Uwaga: ten operator nie pozwala podawać //deskryptora_pliku// (''&'' jest odczytywane jako deskryptor) \\ otwiera plik //słowo// do zapisu, ucina go, duplikuje go i zastępuje zarówno 1 jak i 2 nowo otwartym plikiem |
| ''&>>''| Uwaga: to jest rozszerzenie powłoki Bash \\ Uwaga: ten operator nie pozwala podawać //deskryptora_pliku// (''&'' jest odczytywane jako deskryptor) \\ otwiera plik //słowo// do dopisywania, duplikuje go i zastępuje zarówno 1 jak i 2 nowo otwartym plikiem |
~~Zadanie.#~~ Uruchom ''cat /etc/motd'' z zamkniętym deskryptorem standardowego wyjścia.
\\
Uruchom ''find /var/spool/'' z zamkniętym deskryptorem standardowego błędu.
~~Zadanie.#~~ Przekieruj standardowe wyjście i standardowy błąd komendy ''cat /etc/motd /etc/shadow'' do jednego pliku bez użycia nieprzenośnej składni ''&>''.
~~Zadanie.#~~ Skopiuj duży plik tekstowy (np. ''/etc/services'') do pliku //p//.
\\
Uruchom ''hexdump'' przekierowując wejście z pliku //p// używając operatora ''<>'',
i zduplikuj standardowe wejście do standardowego wyjścia. Sprawdź co się stało.
\\
Uwaga: nie używaj dwukrotnie ''<>'' z tym samym plikiem dla standardowego wejścia
i standardowego wyjścia (chyba że jesteś gotowy ponieść konsekwencje swojego czynu).
~~Zadanie.#~~ Zamień miejscami standardowe wyjście i standardowy błąd komendy
''cat /etc/motd /etc/shadow''. \\ Sprawdź działanie dodając ''|rev'' na koniec
(co odwróci kolejność znaków na standardowym wyjściu).
=== Przekierowania standardowych strumieni bieżącej powłoki ===
Wykonanie przekierowania na komendzie ''exec'' spowoduje przekierowanie standardowych strumieni bieżącej powłoki.
exec 3>&1 # duplikuje standardowe wyjście do deskryptora 3
exec 1>plik # zastępuje standardowe wyjście plikiem 'plik'
date # wypisuje datę na standardowe wyjście (którym jest teraz 'plik')
fortune # " fortunkę "
exec 1>&3 3>&- # przywraca poprzednie wyjście (duplikując je z deskryptora 3) i zamyka 3
=== Process substitution (rozszerzenie Basha) ===
[[https://www.gnu.org/software/bash/manual/html_node/Process-Substitution.html|Dokumentacja Basha na temat process substitution]]
Składnia ''komenda1 <(komenda2)'' i ''komenda1 >(komenda2)'' __nie__ są przekierowaniami.
Bash zastępuje ''<(komenda)'' nazwą tymczasowego pliku (pipe), uruchamia w tle polecenie ''komenda'' ustawiając jego standardowe wyjście na plik tymczasowy.
Bash zastępuje ''>(komenda)'' nazwą tymczasowego pliku (pipe), uruchamia w tle polecenie ''komenda'' ustawiając jego standardowe wejście na plik tymczasowy.
~~Zadanie.#~~ Wykonaj i zrozum wyniki poleceń:
* przydatnych:
* ''paste <(hostname) <(date +%Y.%m.%d) <(uptime)''
* ''cat /etc/motd /etc/shadow 2> >(rev) > >(hexdump -C)''
* prezentujących działanie process substitution:
* ''/bin/ls -l >(echo a) >(echo b) <(echo c)''
* ''stat >(echo c)''
* ''stat >(sleep 3; fortune)''
* ''cat <(echo a)''
* ''echo 'abc' > >(rev)''
* ''cat <(date) > >(rev)''
* ''cat < <(date) > >(rev)''
* ''cat <(date) <(date) <(date) > >(rev)''
* ''cat <(date) <(date) < <(date) > >(rev)''
~~META:
language = pl
~~