===== 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. ''**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 (to ostatnie można wyłączyć podając ''-n''). \\ Przełącznik ''-e'' powoduje zamianę sekwencji takich jak ''\t'' czy ''\n'' na odpowiadające im znaki (tutaj: tab i nowa linia). ''**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 z tym samym plikiem dla standardowego wejścia i standardowego błędu (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 ~~