Laboratorium Architektury Komputerów
i Systemów Operacyjnych
Ćwiczenie 6
Polecenia systemu Unix/Linux, łączenie poleceń, programowanie w języku
powłoki
Wprowadzenie
System operacyjny Linux należy do rodziny systemów uniksopodobnych. System Unix
powstał w 1969 r. w laboratoriach firmy ATT. Na przestrzeni minionych lat stał się jednym z
głównych systemów operacyjnych stosowanych w stacjach roboczych, serwerach
obliczeniowych, serwerach sieciowych, itp. Powstało wiele wersji systemu, nieznacznie
różniących się ze względu na ograniczenia patentowe i licencyjne. Pojawiły się także wersje
na procesory typu i386/486, np. SCO Unix (firmy później wykupionej przez SUN). Linux
powstał w 1991 roku, gdy fiński informatyk Linus Torvald poinformował o utworzeniu przez
siebie hobbystycznego systemu operacyjnego na procesory i386/486. Powstały system tylko z
zewnątrz (od strony użytkowej) przypominał Unix, natomiast wewnątrz prezentował zupełnie
inną koncepcję w zakresie rozwiązań technicznych. Był oparty o jądro, które było
konfigurowane do konkretnych zastosowań i następnie kompilowane. Do jądra dołączono
biblioteki pochodzące z projektu GNU (GNU means Not Unix). Dzięki temu system działał
szybciej od porównywalnych rozwiązań uniksowych. Linux jest jednym z przykładów
wolnego i otwartego oprogramowania, a jego kod może być dowolnie wykorzystywany,
modyfikowany i rozpowszechniany (opensource - licencja GNU PL). Obecnie jest on
udostępniany w formie licznych dystrybucji Linuksa (np. Debian, Red Hat, Suse) które
składają się z jądra (niekiedy zmodyfikowanego w stosunku do oficjalnej wersji) i zestawu
pakietów oprogramowania dobranego do różnorodnych wymagań. Dystrybucje zawierają
głównie oprogramowanie na licencjach opensource, ale można dodać do nich
oprogramowanie licencjonowane.
Najbardziej częstym zastosowaniem Linuksa to serwery sieciowe (poczta, ftp, zapory
sieciowe, serwisy www, systemy NIDS i HIDS), ale także jest stosowany w multimediach
(systemy wbudowane np. urządzeniach DVD, telefonach, i-podach) i w dużych systemach
wielomaszynowych i wieloprocesorowych (np. TASK, symulacje filmowe, np. Star Wars).
Korzystają z niego urzędy administracji państwowej (ale nie w Polsce ), służby specjalne,
organizacje biznesowe, np. giełdy.
Linuks oferuje wiele możliwości pracy z systemem. Można tworzyć dokumenty i prezentacje,
używając pakietu OpenOffice (to nie jest część Linuksa), grafikę, a także administrować
zasobami systemu z poziomu interfejsu okienkowego oraz terminalowego. Ten ostatni sposób
bezpośrednio wywodzi się z systemu Unix – był przez długi okres czasu jedyną metodą
komunikacji z systemem operacyjnym. W niektórych specjalizowanych zastosowaniach (np.
systemy wbudowane, urządzenia sieciowe, itp.) jest to jedyny interfejs systemu.
2
Informacje wstępne
Celem ćwiczenia laboratoryjnego nr 6 jest:
poznanie przez uczestników zajęć podstawowych poleceń systemu UNIX,
poznanie roli zmiennych otoczenia,
poznanie i utrwalenie wiedzy dot. budowy systemu operacyjnego, struktury
katalogów, zasad realizacji poleceń;
wprowadzenie do programowania w języku powłoki.
Realizacja omawianego ćwiczenia laboratoryjnego wymaga:
znajomości metod uruchamiania programów w środowisku Windows/Linux,
umiejętności programowania w języku C,
znajomości podstawowych pojęć z architektury systemów komputerowych.
Do wykonania niniejszego ćwiczenia używane będą narzędzia programistyczne dostępne w
laboratoriach Wydziału ETI PG.
Aby zaliczyć ćwiczenia laboratoryjne, student musi wykonać poprawnie polecenia i zadania
podane przez prowadzącego. Poprawna odpowiedź za zadawane w trakcie pytania wpłynie na
wysokość oceny.
Podstawowe polecenia systemu Unix/Linux
Polecenie składa się z następujących elementów:
<nazwa_polecenia> -<opcje> <parametry>
gdzie:
<nazwa_polecenia> jest nazwa jakiegokolwiek programu, funkcji powłoki lub funkcji
wewnętrznej powłoki.
<opcje> to najczęściej zestaw pojedynczych liter określających sposób wykonania
programu.
<parametry> to informacje dla programu (funkcji) co właściwie ma wykonać.
Uwaga: w systemie jest dostępny podręcznik opisujący działanie poleceń systemowych. W
celu uzyskania informacji należy wprowadzić polecenie postaci:
man <nazwa_polecenia>
Przykładowo, wpisanie:
man ls
spowoduje wyświetlenie opisu polecenia ls wraz z opcjami dostępnymi w danej wersji
systemu.
Polecenie cd
Polecenie to służy do zmiany aktualnego katalogu. Jeśli nie podamy argumentu, domyślnie
przyjmowany jest katalog domowy podany w zmiennej $HOME. Katalog / oznacza główny
katalog systemu Linux/Unix.
3
Polecenie ls – wyświetl zawartość katalogu
Jeśli nie podamy żadnego argumentu, zostanie wyświetlona zawartość katalogu aktualnego
(miejsca, w którym aktualnie „znajduje się” użytkownik). Często stosowane opcje (pozostałe
opisane są w podręczniku man):
-R
rekursywnie wyświetlaj poddrzewo;
-a
wyświetl wszystkie pozycje skorowidza, nawet rozpoczynające się od '.';
-d
nie listuj zawartości skorowidzów;
-i
podaj numery węzłów dla plików;
-l
długi listing: tryb (typ i uprawnienia), liczba łączników, właściciel, grupa,
wielkość, czas ;
-r
odwróć porządek sortowania;
-s
podaj wielkość w blokach;
-t
sortuj w/g czasu, najnowsze na początku.
Po wpisaniu poleceń
cd /
ls –l
otrzymujemy następujący wydruk (w przybliżeniu – dla różnych wersji systemu Linux może
wyglądać nieznacznie inaczej) na ekranie terminala głównego katalogu systemowego:
razem 80
drwxr-xr-x 2 root root 4096 2008-10-07 22:25 bin
drwxr-xr-x 3 root root 4096 2008-10-28 18:31 boot
lrwxrwxrwx 1 root root 11 2008-10-07 21:30 cdrom -> media/cdrom
drwxr-xr-x 13 root root 4280 2009-03-06 12:03 dev
drwxr-xr-x 108 root root 4096 2009-03-06 12:02 etc
drwxr-xr-x 3 root root 4096 2008-10-07 22:30 home
drwxr-xr-x 2 root root 4096 2008-10-07 21:32 initrd
lrwxrwxrwx 1 root root 28 2008-10-07 21:34 initrd.img ->
boot/initrd.img-2.6.18-6-686
drwxr-xr-x 15 root root 4096 2008-10-07 22:25 lib
drwx------ 2 root root 16384 2008-10-07 21:30 lost+found
drwxr-xr-x 4 root root 4096 2008-11-12 13:33 media
drwxr-xr-x 2 root root 4096 2006-10-28 16:06 mnt
drwxr-xr-x 2 root root 4096 2008-10-07 21:32 opt
dr-xr-xr-x 144 root root 0 2009-03-06 13:02 proc
drwxr-xr-x 8 root root 4096 2008-11-17 20:15 root
drwxr-xr-x 2 root root 4096 2008-10-07 22:30 sbin
drwxr-xr-x 2 root root 4096 2007-03-07 23:56 selinux
drwxr-xr-x 2 root root 4096 2008-10-07 21:32 srv
drwxr-xr-x 11 root root 0 2009-03-06 13:02 sys
drwxrwxrwt 10 root root 4096 2009-03-06 12:17 tmp
drwxr-xr-x 11 root root 4096 2008-10-07 22:20 usr
drwxr-xr-x 15 root root 4096 2008-10-07 22:28 var
lrwxrwxrwx 1 root root 25 2008-10-07 21:34 vmlinuz -> boot/vmlinuz-
2.6.18-6-686
Zadania do wykonania:
a. W podobny sposób obejrzyj zawartość katalogów dev, etc, bin, usr. Jak
interpretujemy ich zawartość?
b. Po wpisaniu poleceń
cd $HOME
4
ls –a
otrzymujemy wydruk na ekranie terminala katalogu domowego. Porównaj wydruki po
wykonaniu polecenia: ls –l. Jaką widzisz różnicę? Co oznaczają pliki o nazwie
zaczynającej się od znaku kropki?
Polecenie cat – połącz (concatenate) i wyświetl pliki
Polecenie wyświetla kolejno na standardowym wyjściu (ekran terminala) kolejne pliki,
których nazwy są umieszczone w wierszu polecenia. Możemy wyświetlane pliki połączyć w
jeden nowy plik, przekierowując odpowiednio standardowe wyjście, np.:
cat plik1 plik2 plik3 > plik4
//połącz trzy pliki w jeden
Znaki // oddzielają komentarz od polecenia i nie są interpretowane. Uwaga: polecenie cat
można w tej formie używać zamiennie z poleceniem cp (kopiuj pliki)
Zadanie do wykonania:
Wyświetl zawartość pliku .bash_profile. Połącz (powiel) ten plik, tworząc inny plik
roboczy o nazwie rob_profile.
Polecenia more i less
Polecenia te stanowią rodzaj filtru, wyświetlając zawartość pliku (będącego argumentem
polecenia) na ekranie terminalu w porcjach wielkości strony (typowo 25 wierszy). Polecenie
more ma charakter jednokierunkowy (nie można cofnąć się do poprzednio wyświetlanej
strony), natomiast polecenie less pozwala poruszać się w obu kierunkach. Zakończenie
polecenia następuje po naciśnięciu znaku q (quit).
Polecenia mkdir i rmdir
Polecenia służą, odpowiednio, do utworzenia i usunięcia katalogu, którego nazwa jest
argumentem. Używając tzw. znaków specjalnych (wildcards) można usunąć więcej jak jeden
katalog.
Zadanie do wykonania:
Utwórz katalog roboczy w katalogu domowym o nazwie: nazwisko_studenta.
Następnie usuń ten katalog i ponownie utwórz.
Polecenia cp, rm, mv
Polecenie cp służy do kopiowania plików. Sposób użycia, np.:
$ cp plik1 plik2 plik3 /usr/tst/tmp
// skopiuj trzy pliki do katalogu /usr/tst/tmp
Polecenie cp kopiuje zawartości katalogów (grupy plików) do innego katalogu. Polecenie
rm usuwa plik, a także grupy plików. Na przykład
rm *
5
spowoduje usunięcie wszystkich plików w danym katalogu. Będąc administratorem możemy
w ten sposób usunąć zawartość całego systemu plików!!!
Często stosowane opcje polecenia rm (pozostałe opisane są w podręczniku man):
-f rm działa bez zadawania pytań użytkownikowi
-i
wymusza tryb interaktywny, nawet gdy standardowym wejściem nie jest
terminal
-r
rekursywnie usuwa zawartość skorowidzów i same skorowidze,
wyspecyfikowane w parametrach wywołania
Polecenie mv przenosi plik do innego (wskazanego) katalogu i/lub zmienia jego nazwę, np.:
// przenieś trzy pliki do katalogu /u/tmp
$ mv plik1.txt plik2.txt plik3.txt /u/tmp
Zadanie do wykonania:
Przenieś powielone pliki do nowego katalogu.
Polecenia zmiany uprawnień chmod, umask, chown, chgrp
Polecenie chmod służy do zmiany (ustawienia) praw dostępu do pliku. Może tego dokonać
jedynie właściciel pliku lub administrator (superuser, root). Maskę uprawnień podajemy w
postaci liczby oktalnej, np.:
// pozwól wszystkim użytkownikom wykonywać plik mtest,
// grupie czytać go, a właścicielowi czytać i pisać
$ chmod 751 mtest
Uwaga: podczas przygotowywania skryptów należy użyć tego polecenia w stosunku do pliku
zawierającego tekst skryptu, aby można go było później uruchomić.
Polecenie umask pozwala ustawić nową maskę uprawnień nadawaną domyślnie plikom
podczas ich tworzenia. Wykonanie polecenia bez argumentu wyświetla aktualną maskę
uprawnień.
Polecenia chown, chgrp służą do zmiany właściciela lub grupy pliku i są używane
najczęściej podczas instalacji bądź rekonfiguracji złożonych aplikacji, np. baz danych.
Zadanie do wykonania:
Wyświetl, a następnie zmień maskę uprawnień.
Polecenia zarządzania procesami: ps, kill
Polecenie ps służy do wyświetlenia listy aktualnych procesów. Typowe opcje to:
-e
wyświetl wszystkie procesy
-f
generuj pełną informację o procesach
6
-t termilist wyświetl procesy związane z terminalem termlist
-u uidlist
wyświetl procesy związane z użytkownikiem uidlist
-g gidlist
wyświetl procesy związane z grupą gidlist
Zadanie do wykonania:
Wyświetl listę procesów własnych, a następnie wszystkich z pełnym opisem.
Polecenie kill służy do przesłania sygnału danego typu do wskazanego procesu, np.
// wyślij sygnał 9 do procesu 1132
$ kill -9 1132
Powoduje bezwzględne zakończenie działania procesu o identyfikatorze 1132.
Środowisko powłoki
Powłoka, aby poprawnie pracować, musi mieć określone środowisko. Składa się ono z
podstawowych dwóch elementów:
katalogu aktualnego,
zmiennych powłoki.
Katalog aktualny (inaczej bieżący) to plik, który dla powłoki jest katalogiem odniesienia. Po
rozpoczęciu pracy najczęściej katalogiem bieżącym jest katalog macierzysty (ang. home
directory). Katalog aktualny zmieniamy poleceniem cd, np.
cd /usr/bin
Zmienne powłoki określają poszczególne elementy środowiska. Część zmiennych jest
predefiniowanych, tzn. mają swoją wartość już przy rozpoczęciu pracy. Zmienne powłoki
przechowują wartości tekstowe. Wartości zmiennych można wykorzystywać w funkcjach i
procedurach powłoki, można tworzyć nowe zmienne, można zmieniać ich wartość. Zmienne
powłoki mogą być lokalne lub globalne. Utworzenie nowej zmiennej lub zmiana wartości
odbywa się poleceniem:
<nazwa_zmiennej>=<wartość>
Tab 1. Zestaw typowych zmiennych powłoki
Nazwa
Wartość
Przykład
HOME
katalog macierzysty
/usr/student
PATH
ścieżka poszukiwań
/bin:/usr/bin:/usr/student/bin:.
TERM
typ terminala
ansi
PS1
pierwszy (główny) znak
zachęty
$
PS2
drugi (pomocniczy) znak
zachęty
>
LOGNAME
nazwa użytkownika
student
TZ=
nazwa strefy czasowej
GMT-1
nazwa pliku - skrzynki
pocztowej
/usr/mail/michk
Należy bezwzględnie zwrócić uwagę na brak spacji przed i po znaku równości - jeśli byśmy
napisali np. coś takiego
7
PATH = /bin:/usr/bin
to powłoka zinterpretuje to jako wywołanie programu o nazwie PATH i dwóch parametrach:
= oraz /bin:/usr/bin
Przykłady nadawania wartości:
PATH=/bin:/usr/bin
ala=ma_kota
piec=555
ala=teraz_taki_sobie_tekst
Ale
ala=taki sobie tekst
oznacza tymczasowe nadanie zmiennej ala wartości taki, a następnie wykonanie programu
o nazwie sobie z jednym parametrem – tekst. W ten sposób powłoka umożliwia nadanie
zmiennej wartości tylko na czas wykonania polecenia (w tym przypadku sobie).
W poleceniach odwołujemy się do zmiennych powłoki, poprzedzając ich nazwę znakiem $,
np.:
cd $HOME
spowoduje powrót do katalogu macierzystego.
Wartości poszczególnych zmiennych możemy obejrzeć poprzez polecenie echo, np.:
echo $PATH
wyświetli na ekranie wartość zmiennej PATH.
Wartości wszystkich zmiennych od razu wyświetla polecenie set. Zmienne są wyświetlane
w kolejności alfabetycznej. Często pojawia się problem kolizji nazw zmiennych. Jeśli mamy
zdefiniowaną następującą zmienną:
ala=tekst
to użycie jej w postaci
echo $alaxyz
spowoduje wyświetlenie tekstu:
tekstxyz
Jeśli dodatkowo zdefiniujemy zmienną:
alaxyz=coś_innego
to poprzednie polecenie echo oczywiście wyświetli teraz wartość zmiennej alaxyz:
coś_innego
Aby uzyskać wartość zmiennej ala, w takiej sytuacji stosuje się nawiasy klamrowe:
echo ${ala}xyz
powoduje wyświetlenie
tekstxyz
8
Przetwarzanie potokowe na poziomie powłoki
Interpreter poleceń umożliwia automatyczne przekazywanie danych wyjściowych z jednego
programu (procesu) jako danych wejściowych dla innego programu — mechanizm ten,
określany jest jako przetwarzanie potokowe (ten sam termin używany jest w innym znaczeniu
w zagadnieniach architektury procesorów). Przetwarzanie potokowe realizowane jest za
pomocą łączy komunikacyjnych (ang. pipes), które oznacza się symbolem |. Takie łącze
tworzy się poprzez bezpośrednie związanie standardowego strumienia wyjściowego procesu
poprzedzającego ze standardowym strumieniem wejściowym innego, następnego procesu.
Przetwarzanie potokowe w systemie Windows (zapożyczone z systemu Unix) i Linux
uruchamia się w identyczny sposób, np.:
$ oblicz | sortuj
(Linux)
C:\> oblicz | sortuj
(Windows)
W systemie Linux, łącza implementowane są jako bezpośrednia komunikacja między
procesami. Niekiedy używany jest tee (rozgałęźnik T), który kopiuje standardowy strumień
wejściowy do standardowego strumienia wyjściowego, tworząc przy tym dodatkową kopię w
podanym pliku, np.
$ ftp ftp.mv.com | tee rejestracja.txt
Filtry stanowią specyficzną odmianę programów usługowych, które zazwyczaj operują na
tekstach (strumieniach znaków) i przeznaczone są wyodrębniania i przekształcania określonej
informacji. Źródłem i przeznaczeniem strumienia znaków mogą być pliki, inne programy lub
dowolne urządzenia znakowe. Operacje wykonywane przez filtry obejmują najczęściej:
— sortowanie pliku wejściowego,
— usuwanie linii tekstu wg przyjętego kryterium,
— zastępowanie wskazanych łańcuchów znakowych przez inne,
— szyfrowanie i deszyfrowanie.
Filtry stosowane są szeroko w systemie Linux. W systemie Linux i Windows są dostępne
m.in. filtry sort i more. Przykładowe wywołanie może mieć postać:
$ ls –l | sort
(Linux)
C:\> dir | sort
(Windows)
Filtry pobierają informacje ze standardowego wejścia i po przetworzeniu przesyłają je do
standardowego wyjścia; przekształcanie realizowane jest wg reguły "znak po znaku" lub
"linia po linii".
Logowanie się do systemu
Do zalogowania się w systemie Linux Fedora potrzebujemy użyć nast. Danych:
login: student
password: student
Po uruchomieniu systemu otwieramy okno terminala, wybierając opcje:
Aplikacje-Narzędzia systemowe->Terminal.
Następnie należy wykonać kolejno opisane polecenia, używając opcji wskazanych przez
prowadzącego zajęcia.
9
Zadania do wykonania:
Wykonaj proste ćwiczenia związane z poleceniami systemu, podane na stronach 3,4,5.
Następnie wykonaj poniższe zadania.
Zadanie 1.
a) wyświetl aktualne zmienne powłoki,
b) utwórz nową zmienną, będącą konkatenacją zmiennych HOME i PATH,
c) wyświetl wartość nowej zmiennej.
Zadanie 2.
a) Używając edytora, np. Aplikacje->Akcesoria->edytor tekstu, utwórz
plik w katalogu o nazwie będącej nazwiskiem studenta zawierający wśród innego
tekstu frazę np. Ala ma kota, a kot myszke.
b) Skopiuj plik na inny, zmieniając bądź dodając inne fragmenty tekstu. Tekst
wyróżniony powinien jednak pozostać w niezmienionej formie.
c) Powtórz krok podany w pkt. b) kilka razy.
d) Nadaj plikom wydłużenie nazwy .txt.
e) Wykonaj polecenie
grep 'Ala ma kota' *.txt | more
Wykonaj ponownie polecenie, przekazując wynik do dowolnego nowego pliku. Nie
zapomnij poprzedzić nazwy pliku pełną ścieżką dostępu.
Zadanie 3.
Napisz wiersz polecenia, który wyszukuje w listingu wszystkie pliki należące do danego
użytkownika i zapisuje wynik do pliku.
Zadanie 4.
a) używając polecenia ls, wyświetl zawartość wskazanego przez prowadzącego
katalogu, sortując wg ustalonego kryterium.
b) Powtórz działanie z p. a, używając potoku i polecenia sort. Sortowania dokonać wg
wskazanej przez prowadzącego kolumny.
ls –l | sort –t' '
10
Podstawy programowania w języku powłoki
Powłoka (ang. shell) jest programem umożliwiającym pracę z systemem Linux. Jej
nazwa wywodzi się z graficznej prezentacji systemu, w której jądro i procesy obsługi wejścia
i wyjścia są otoczone właśnie przez powłokę. Jej funkcją jest odseparowanie użytkownika od
bezpośredniego dostępu do jądra systemu i umożliwienie łatwej i wszechstronnej pracy.
Podstawowym zadaniem powłoki jest przyjmowanie poleceń użytkownika i
uruchamianie stosownych programów. Do dalszych funkcji powłoki należy konstruowanie
parametrów dla poleceń oraz zarządzanie sposobem wykonywania programów – procesów.
Następnym, bardziej skomplikowanym krokiem jest tworzenie funkcji i procedur powłoki
(skryptów) pozwalających na łączenie wielu poleceń w jedno, umożliwiając pisanie całych
programów dla powłoki.
Powłoka jest programem, z którym użytkownik systemu Linux spotyka się na samym
początku. Jej uruchomienie następuje automatycznie, bezpośrednio po zalogowaniu
(zgłoszeniu) użytkownika w systemie. Gdy widzimy na ekranie znak $, oznacza to, że
powłoka jest już uruchomiona i oczekuje na podawanie poleceń.
System Linux oferuje wiele powłok. W czasie zajęć przede wszystkim zostanie
omówiona powłoka standardowa oznaczana skrótem sh i zwana Bourne shell.
Podstawowymi poleceniami są dwa następujące:
: <dowolne parametry>
# komentarz
Pierwsza z nich (dwukropek) to polecenie puste – nic nie robi, zwraca kod błędu 0. Drugie
(hash) to komentarz – tym się różni od poprzedniego, że nie zmienia zmiennej $? - kodu błędu
ostatnio wykonanego procesu.
Normalnie powłoka postępuje w taki sposób, że po uruchomieniu programu czeka na
zakończenie jego wykonania i dopiero wtedy znów wyświetla znak zachęty i oczekuje na
wprowadzenie następnego polecenia. Można jednakże uruchomić program "w tle", to znaczy
powłoka nie będzie czekała na zakończenie jego działania, tylko od razu wyświetli znak
zachęty. Przykład:
$ obliczenia dane.txt &
[2313]
$
Znak & podany na końcu polecenia powoduje jego uruchomienie w tle.
Wykaz zmiennych polecenia powłoki:
Nazwa
Wartość
Przykład
$0
nazwa wykonywanego programu
sh
$1
pierwszy parametr wywołania
ala.txt
$2...$9 następne parametry wywołania
prog.c
$*
wszystkie parametry wywołania
ala.txt prog.c
$@
jw, ale parametry jako osobne łańcuchy znaków
"ala.txt" "prog.c"
$#
liczba parametrów
2
$-
opcje powłoki podane przy wywołaniu
-xv
$?
kod błędu ostatnio wykonanego polecenia
0
$$
numer procesu powłoki
12345
$!
numer procesu ostatnio wykonanego w tle
12560
11
A oto sposób utworzenia pliku tymczasowego o unikalnej nazwie:
/tmp/plik.$$
Przekierowanie wejścia i wyjścia, potoki
Każdemu procesowi na początku jego pracy system udostępnia trzy strumienie:
standardowe wejście - strumień o numerze 0,
standardowe wyjście - strumień o numerze 1,
standardowe wyjście błędu - strumień o numerze 2.
Powłoka uruchamiając każdy proces udostępnia mu swoje standardowe strumienie.
Ponieważ na początku ich rolę pełni terminal (wejście – klawiatura, wyjście – ekran), więc i
programy – procesy uruchamiane przez użytkownika będą miały tak przyporządkowane
strumienie.
Istnieje możliwość zmiany ustawienia strumieni – przekierowanie (ang. redirection).
Wiele programów systemu Unix to tzw. filtry, czyli czytające tylko ze standardowego wejścia
i piszące tylko na standardowe wyjście. Używając mechanizmu przekierowania można
uzyskać efekt ich pracy na plikach. Przekierowanie wyjścia może odbywać się dwoma
sposobami:
polecenie > nazwa_pliku
polecenie >> nazwa_pliku
Pierwszy sposób powoduje zapisanie do pliku nazwa_pliku całego standardowego
wyjścia z polecenia. Jeśli taki plik istniał, jego poprzednia zawartość zostanie usunięta. Drugi
sposób powoduje dopisanie wyjścia standardowego z polecenia do ew. istniejącej już
zawartości pliku.
Przekierowanie wejścia realizujemy następująco:
polecenie < nazwa_pliku
Proces uruchomiony poleceniem będzie odczytywał dane z pliku nazwa_pliku, a nie z
terminala.
Z pojęciem przekierowania łączy się też mechanizm następujący:
polecenie << słowo
Mechanizm ten nie ma zastosowania w pracy interakcyjnej. Podczas pisania procedur
powłoki (skryptów) można w ten sposób uzyskać efekt odczytu danych przez program z
samego skryptu.
Wszystkie programy systemu Linux swoje komunikaty diagnostyczne wyprowadzają
na standardowe wyjście błędów (standardowo też ekran terminala). W przypadku
przekierowania wyjścia standardowego
1) unikamy niepotrzebnych komunikatów diagnostycznych w pliku. Najczęściej jest on
wejściem do następnego programu, dla którego komunikat diagnostyczny jest
bezsensowny,
2) uzyskujemy na terminalu informację o błędzie. Jeśli program zauważa błąd w danych,
to wyświetla komunikat; gdyby komunikat też był przekierowany do pliku, użytkownik w
ogóle nie zorientowałby się, że zdarzyła się błędna sytuacja.
Jeżeli nie chcemy, aby komunikaty o błędach pojawiały się na ekranie, to możemy
niezależnie przekierować standardowe wyjście błędów. Odbywa się to w sposób:
12
polecenie 2> nazwa_pliku
Można też połączyć kilka strumieni w jeden, podając np. że wyjście ze strumienia 5 ma być
połączone z wyjściem strumienia 1 (standardowego wyjścia):
polecenie 5>&1
Przekierowania są ważnym elementem w przypadku wykonywania programów w tle.
Standardowym wejściem takiego programu jest /dev/null, czyli wejście puste, zaś
wyjściem jest terminal. Aby uniknąć pomieszania informacji na ekranie, stosuje się
przekierowanie:
program <dane.txt >wyniki.txt 2>bledy.txt &
Przykłady:
Typowym poleceniem dla przykładów na przekierowanie jest polecenie cat:
cat plik_1 plik_2 ... plik_n
Gdy nie podamy żadnych parametrów poleceniu cat, to odczyt następuje ze standardowego
wejścia, więc w takim wypadku cat po prostu kopiuje standardowe wejście na standardowe
wyjście.
cat prog.c > prog1.c
powoduje przekopiowanie zawartości pliku prog.c do pliku prog1.c
cat <prog.c >prog1.c
daje efekt identyczny
cat *.txt >wszystkie 2>bledy
kopiuje wszystkie pliki o nazwach kończących się na .txt do pliku wszystkie, zaś
komunikaty o błędach trafiają do pliku bledy.
cat *.txt >/dev/null
Polecenie
cat <ala.txt >ala.txt
spowoduje wyzerowanie pliku ala.txt! Dlaczego?
Bardzo często wyjście jednego polecenia jest wejściem następnego, np.
ls /usr/student >/tmp/mkdir
grep abcd </tmp/mkdir
rm /tmp/mkdir
lub równoważne polecenie z użyciem potoku
ls /usr/student | grep abcd
ls /usr/student | grep abcd | more
Ewentualne przeadresowania wejścia i wyjścia odnoszą się tylko do poszczególnych poleceń,
np.
ls /usr/student | grep abcd 2>bledy
13
powoduje przekierowanie standardowego wyjścia błędu tylko polecenia grep. Można
uzyskać łączne przekierowanie stosując grupowanie poleceń.
Rozwijanie nazw plików i cytowanie
Można używać następujących metaznaków:
*
pasuje do dowolnego tekstu
?
pasuje do dowolnego znaku
[...] pasuje do każdego znaku z wymienionych między nawiasami
[x-y] pasuje do każdego znaku znajdującego się pomiędzy x i y (z nimi włącznie)
[!..] pasuje do każdego znaku z wyjątkiem znaków podanych po wykrzykniku.
Uwaga: Poszczególne formy [] można łączyć ze sobą, np. [a-zA-Z0123456789]
Wyobraźmy sobie strukturę skorowidzów:
/usr/student/
ala.txt
info.1
prog.c
obliczenia/
dane1.txt
wyniki.txt
rozne/
rozne.1
rozne.2
rozne.3
Katalogiem bieżącym jest /usr/student
Warto zwrócić uwagę, że występująca kropka w nazwach plików nie rozdziela nazwy od
rozszerzenia (jak w Windows), ale jest po prostu elementem nazwy takim samym, jak każdy
inny znak.
Powłoka zawsze dokonuje rozwinięcia w kolejności alfabetycznej.
Metaznak
Wynik
*.1
info.1 (ale nie rozne/rozne.1 !)
*/*
obliczenia/dane1.txt obliczenia/wyniki.txt
rozne/rozne.1 rozne/rozne.2 rozne/rozne.3
[a-k]*
ala.txt info.1
[!abc]*c
prog.c obliczenia rozne
*o*
info.c obliczenia rozne prog.c
*.?
info.1 prog.c
14
*.??
*.?? (nic nie pasuje)
*.???
ala.txt
*[!.]*
obliczenia rozne
cat *.?
powoduje, że program cat otrzyma jako pierwszy parametr info.1, jako drugi prog.c,
czyli tak, jakby podać polecenie:
cat info.1 prog.c
Cytowanie znaków (substytucja)
Czasami nie chcemy, aby powłoka rozwijała nazwy plików. Przykładem może być
polecenie find:
find . -name *.txt -print
powoduje wyszukanie i wyświetlenie nazw wszystkich plików pasujących do podanego
wzorca – w tym przypadku *.txt. Przeszukiwane są katalogi: bieżący i wszystkie
podkatalogi.
Takie podanie polecenia powłoce spowoduje jednak rozwinięcie nazwy pliku i w rezultacie
program find otrzyma następujące parametry:
find . -name ala.txt –print
co całkowicie zmienia znaczenie – teraz znalezione będą tylko pliki o nazwie ala.txt.
Aby zabronić powłoce dokonywania substytucji, stosowane jest cytowanie znaków. Są
dostępne następujące mechanizmy:
poprzedzanie znakiem "\" (backslash). Każdy znak po nim nie jest interpretowany przez
powłokę, a więc można nasze polecenie podać w sposób następujący:
find . -name \*.txt –print
tym znakiem możemy podać programowi wszystkie znaki, włącznie z takimi, które są
interpretowane przez powłokę:
program dane.tx \&
spowoduje przekazanie znaku "&" do programu, a nie wykonanie programu w tle.
poprzez ujęcie tekstu w cudzysłowy, np.
find . -name "*.txt" -print
takie cytowanie powoduje, że nie jest dokonywane rozwinięcie nazw plików w tekście
w cudzysłowach oraz dodatkowo, cały tekst ujęty w cudzysłowy jest traktowany jako
pojedynczy parametr dla polecenia.
grep "ala ma kota" dane.txt
powoduje wyszukanie tekstu ala ma kota w pliku dane.txt.
15
$ echo "To jest
> wielowierszowy pojedynczy
> parametr dla polecenia
> echo i tak właśnie będzie wyświetlony"
poprzez ujęcie tekstu w apostrofy:
find . -name ‘*.txt’ -print
od poprzedniego rozwiązania różni się tym, że nie jest dokonywana tutaj żadna
substytucja, także nazw zmiennych.
Zestaw poleceń
nazwa=\*.txt
echo $nazwa
echo ”$nazwa”
echo ‘$nazwa’
spowoduje wyświetlenie kolejno
prog.txt
*.txt
$nazwa
Substytucja poleceń
Powłoka jest w stanie wykonać dane polecenie i wyniki jego działania przedstawić
jako listę parametrów dla innego polecenia. Odbywa się to przez umieszczenie jej wywołania
w znakach akcentu, np.:
rm -i 'find . -name *.tmp -print'
Najpierw wykonywane jest polecenie find, podające listę nazw plików odpowiadających
wzorcowi, np.:
./dane.tmp
./info.tmp
./obliczenia/aa.tmp
./obliczenia/bb.tmp
./obliczenia/cc.tmp
Ten wykaz zastępuje polecenie find podane w znakach akcentu i dopiero teraz powłoka
wykonuje polecenie rm:
rm -i ./dane.tmp ./info.tmp ./obliczenia/aa.tmp
./obliczenia/bb.tmp ./obliczenia/cc.tmp
Ten mechanizm jest źródłem dużych możliwości w programowaniu powłoki.
16
Grupowanie poleceń
Polecenia powłoki mogą być zbierane w grupy dwojakiego rodzaju:
- poprzez ujęcie listy poleceń w nawiasy klamrowe {}
- poprzez ujęcie listy poleceń w nawiasy ()
Polecenia w liście rozdzielamy średnikami lub znakami nowej linii; w przypadku nawiasów
klamrowych należy podać też średnik po ostatniej poleceniu.
Ujęcie listy poleceń w nawiasy klamrowe służyć może wspólnemu przekierowaniu
wejścia / wyjścia, np.
{ ls /usr/student | grep abcd ; } 2>bledy
{ cat naglowek.txt; ls -l | grep abcd ; } >info.1
Inne zastosowania grupowania w nawiasy klamrowe to wszystkie takie sytuacje, w
których powłoka wymaga jednego polecenia, a potrzeba wykonać kilka.
Ujęcie poleceń w nawiasy powoduje uruchomienie nowej powłoki (mówimy:
podpowłoki) i wykonanie poleceń przez tę podpowłokę. Taki mechanizm stosuje się, gdy
użytkownik nie chce zmieniać środowiska powłoki.
Ponieważ np. katalog bieżący należy do środowiska, polecenia:
cd / ; ls -l
spowodują wyświetlenie zawartości skorowidza głównego; po czym bieżącym skorowidzem
pozostanie nadal skorowidz główny. Użycie nawiasów:
( cd / ; ls -l )
powoduje taki sam efekt, ale po zakończeniu działania tych poleceń skorowidz bieżący
pozostanie bez zmian, gdyż zmienił się tylko w podpowłoce, która już zakończyła działanie.
Innym zastosowaniem nawiasów może być wykonanie ciągu poleceń w tle, przy
czym wszystkie nie wykonują się niezależnie, ale jedno po drugim:
( cd obliczenia ; oblicz <dane.txt >wyniki.txt
write $LOGNAME "koniec obliczeń") &
Wykonanie względne || i &&
Wykonanie jednego polecenia można uzależnić od efektów działania innego
polecenia. Temu służą dwa operatory: || oraz &&.
Operator || łączący dwa polecenia oznacza, że drugie z nich będzie wykonane tylko
wtedy, gdy wykonanie pierwszego zakończy się błędem. Operator && działa przeciwnie -
drugie polecenie wykonuje się, gdy pierwsze nie kończy się błędem.
17
Kod błędu ostatnio wykonanego programu możemy zawsze badać analizując zmienną
powłoki $?; innym sposobem jest opisywana właśnie konstrukcja:
grep abcd >wynik.txt<dane.txt||echo nie znaleziono!!!
lub też
grep abcd >wynik.txt <dane.txt && echo znaleziono!!!
Oba te operatory można traktować jako skrócone wersje instrukcji if.
Polecenia wewnętrzne
nazwa_pliku
powoduje wykonanie poleceń zawartych w podanym pliku. Należy
odróżnić takie wywołanie od skryptu powłoki, który powoduje utworzenie podpowłoki.
break n
wyjście z pętli for, while lub until. Parametr n oznacza zagłębienie
pętli, domyślnie wynosi 1.
continue n
rozpoczęcie wykonywania pętli for, while lub until od początku.
Parametr n oznacza zagłębienie pętli, domyślnie wynosi 1.
cd katalog
zmiana katalogu bieżącego. Takie polecenie musi być wewnętrzne,
gdyż w przeciwnym wypadku nie dawałoby żadnego efektu -
środowisko powłoki nie ulega zmianie z powodu wykonywania
innych procesów!
eval ...
potraktowanie argumentów jak standardowego wejścia powłoki. np.
program tset podaje na wyjściu tekst "TERM=ansi". Zastosowanie
eval pozwala zdefiniować zmienną TERM:
eval `tset`
powoduje definicję zmiennej TERM na wartość "ansi"
exec ...
powoduje wykonanie podanego polecenia zamiast powłoki - po jej
zakończeniu powłoka już nie istnieje i nie zgłasza się sygnałem
zachęty (gdy jest to powłoka główna, użytkownik zostaje
"wylogowany" - wyrejestrowany z pracy w systemie).
exit n
zakończenie działania powłoki. Parametr podaje kod błędu, domyślnie
0.
export zmienna nadaje globalny zasięg zmiennej. Taka zmienna jest dziedziczona
przez podpowłoki i inne procesy potomne. Samo słowo export, bez
parametrów wyświetla wykaz zmiennych eksportowanych przez
powłokę.
read zmienna
odczytanie jednego wiersza z terminala i wpisanie go jako wartości
podanej zmiennej (tu zmienną jest łańcuch znaków). To polecenie
umożliwia pisanie interakcyjnych skryptów i funkcji.
return n
zakończenie działania funkcji powłoki. Parametr podaje kod błędu,
domyślnie 0.
set
wyświetla zmienne powłoki.
18
set -fntvx
ustawia opcje powłoki (można to robić też przy wywołaniu powłoki,
patrz dalszy rozdział.
set parametry...
ustawia parametry powłoki, dostępne przez $1, $2 itd.
shift n
przesunięcie parametrów. Parametr drugi staje się $1, trzeci $2 itd.
Parametr pierwszy jest tracony. Polecenie użyteczne, gdy parametrów
jest więcej niż dziewięć. Można ew. przesunąć o więcej niż 1, podając
stosowne n.
trap
ustawianie odpowiedzi powłoki na sygnały.
type nazwa...
podaje, jak dana nazwa (nazwy) byłaby zinterpretowana jako
polecenie (wewnętrzna, funkcja, skrypt, program...)
Instrukcje strukturalne (if, case, for, while, until)
Jak wspomniano na wstępie, powłoka oferuje mechanizmy budowy funkcji i procedur
w celu programowania powłoki. W takim przypadku nieodzowne stają się instrukcje sterujące
przepływem programu, ustalające kolejność wykonywanych działań. Powłoka posiada takie
mechanizmy.
Instrukcja if
Syntaktyka:
if <polecenie>
then <lista_poleceń_1>
else <lista_poleceń_2>
fi
Powłoka wykonuje polecenie. Jeśli kod błędu wynosi 0, to wykonywana jest
lista_poleceń_1; w przeciwnym wypadku lista_poleceń_2. Część else jest opcjonalna i nie
musi występować.
Przykład:
if test -f temp.txt
then rm temp.txt
fi
Uwaga: Wszystkie te polecenia można zapisać w jednym wierszu, rozdzielając średnikami
kolejne polecenia:
if test -f temp.txt; then rm temp.txt; fi
Średniki są tu niezbędne; inaczej powłoka nie wiedziałaby, gdzie kończy się jedno polecenie i
zaczyna drugie.
W przypadku wykonywania zagnieżdżonych instrukcji if:
if <polecenie_1>
then <lista_poleceń_1>
else if <polecenie_2>
then <lista_poleceń_2>
else if <polecenie_3>
then <lista_poleceń_3>
19
else <lista_poleceń_4>
fi
fi
fi
można używać konstrukcji łączącej else if w jedno elif:
if <polecenie_1>
then <lista_poleceń_1>
elif <polecenie_2>
then <lista_poleceń_2>
elif <polecenie_3>
then <lista_poleceń_3>
else <lista_poleceń_4>
fi
Można teraz wrócić do poprzedniego rozdziału, z operatorami || i &&. Jak widać oba zapisy
są równoważne:
polecenie_1 && polecenie_2
if <polecenie_1>
then <polecenie_2>
fi
polecenie_1 || polecenie_2
if <polecenie_1>
then
else <polecenie_2>
fi
Instrukcja case
Syntaktyka:
case <słowo> in
<wzór_1> ) <lista_poleceń_1> ;;
...
<wzór_n> ) <lista_poleceń_n> ;;
esac
W przypadku wykonywania tej samej listy poleceń dla kilku wzorów, można podać:
<wzor_1>|<wzor_2>|...|<wzor_i> )<lista_poleceń_i> ;;
Łańcuch <słowo> jest porównywany po kolei z podanymi wzorami. W przypadku
znalezienia zgodności, wykonywana jest odpowiednia lista poleceń. Zgodność jest rozumiana
identycznie jak przy rozwijaniu nazw plików z użyciem metaznaków, więc aby uzyskać
wykonanie listy "otherwise" (gdy żaden wzór nie pasuje), należy na końcu podać wzór w
postaci gwiazdki, jak w przykładzie.
Przykład:
# skrypt o nazwie append
case $# in
1)
cat >> $1 ;;
2)
cat <$1 >>$2 ;;
*)
echo 'składnia: append [z] do' ;;
20
esac
Uwaga: Po wykonaniu stosownej listy poleceń nie są wykonywane kolejne listy, jak to ma
miejsce w języku C - powłoka zachowuje się podobnie do języka Pascal.
Instrukcja for
Składnia:
for <nazwa>
do
<lista_poleceń>
done
for <nazwa> in <lista_słów>
do
<lista_poleceń>
done
Pierwsza z tych form powoduje, że lista poleceń zostanie wykonana tyle razy, ile
parametrów przekazano do powłoki lub skryptu. Zmienna po podanej nazwie nazwa będzie
przyjmowała po kolei wartości tych parametrów.
Przykład:
for i
do
echo $i
done
wyświetli wykaz wszystkich parametrów, każdy w osobnym wierszu.
Druga forma powoduje wykonanie listy poleceń dla każdego słowa w podanej liście
słów. Typowym przykładem jest wykonanie jakiejś akcji dla podanych plików:
for i in *.txt
do
if grep „Plik do skasowania” <$i
then rm $i
fi
done
powoduje usunięcie takich plików, które mają nazwy zakończone na .txt i zawierają napis
"Plik do skasowania". Szczególnie wykorzystując substytucje poleceń można tworzyć
ciekawe konstrukcje, np. ten sam problem, ale wykonany dla wszystkich plików, nie tylko w
bieżącym skorowidzu ale i w podskorowidzach będzie rozwiązany następująco:
for i in `find . -name "*.txt" -print`
do
if grep "Plik do skasowania" <$i
then rm $i
fi
done
21
Instrukcja while
Syntaktyka:
while <lista_poleceń_1>
do <lista_poleceń_2>
done
Wykonanie tej instrukcji polega na wielokrotnym wykonywaniu pierwszej listy
poleceń; w przypadku, gdy kod błędu ostatniego z poleceń w liście wynosi 0, wykonywana
jest druga lista poleceń i proces się powtarza; kod błędu niezerowy oznacza zakończenie tej
pętli.
Przykład:
while
echo -n "Czy wykonać (t/n) "
read x
case $ x in
[tTnN]* ) false ;;
* ) true ;;
esac
do
echo Podaj "t" lub "n"
done
Instrukcja until
Syntaktyka:
until <lista_poleceń_1>
do <lista_poleceń_2>
done
Wykonanie tej instrukcji polega na wielokrotnym wykonywaniu pierwszej listy
poleceń; w przypadku, gdy kod błędu ostatniego z poleceń w liście jest niezerowy,
wykonywana jest druga lista poleceń i proces się powtarza; zerowy kod błędu oznacza
zakończenie tej pętli.
Funkcje powłoki
Powłoka umożliwia definicje funkcji. Funkcje te mogą być później wywoływane.
Definicja funkcji wygląda następująco:
nazwa() polecenie
W ten sposób tworzymy funkcję o nazwie nazwa i treści polecenie. Wywołując funkcję
możemy podawać parametry:
komunikat() { echo błędn$1 $2 w $3 ; }
komunikat y znak pliku
błędny znak w pliku
22
komunikat a linia danych
błędna
linia
w
danych
Przykład:
gettn() {
while
echo -n $*
echo -n " (t/n) ? "
do
read yn reszta
case $yn in
[yY] ) return 0 ;;
[nN] ) return 1 ;;
* ) echo "Proszę podać T lub N" >&2 ;;
esac
done ;
}
Wykorzystanie:
gettn "Czy skasować plik" || break ;
Inny przykład:
ccd () { cd $1 ; PS1="`pwd` $" ;}
Powoduje wyświetlanie bieżącego skorowidza jako znaku zachęty powłoki. Każdorazowe
wykonywanie ccd zamiast cd umożliwia bieżące zmiany znaku zachęty:
$ ccd /usr/bin
/usr/bin $
Procedury powłoki, podpowłoka
Procedury powłoki (skrypty) to zapisane w oddzielnych plikach polecenia powłoki.
Wykonujemy je podając polecenie
sh nazwa_pliku
lub krócej
nazwa_pliku
gdy plik ma ustawiony atrybut wykonywalności x.
Takie wywołanie powoduje uruchomienie nowej powłoki (podpowłoki), która
wykonuje polecenia zapisane w skrypcie. Podpowłoka dziedziczy środowisko, a więc
skorowidz bieżący i wszystkie zmienne globalne powłoki.
Sygnały
Polecenie wewnętrzne trap umożliwia ustawienie reakcji niestandardowej powłoki na
przychodzące do niej sygnały. Składnia tego polecenia jest następująca:
trap <polecenie> n
23
i oznacza, że po wystąpieniu sygnału o numerze n zostanie wykonane polecenie. Pusty
łańcuch oznacza, że dany sygnał ma być zignorowany:
Standardową reakcją powłoki na sygnał INTERRUPT (klawisz <Del>) jest ignorowanie go.
Można jednakże poleceniem
trap exit 2
spowodować, że sygnał ten spowoduje przerwanie pracy powłoki i "wylogowanie"
użytkownika.
Opcje wykonania powłoki
Podczas uruchamiania powłoki oraz w trakcie jej działania możemy podawać opcje.
Uruchamiając podajemy je jak każdemu programowi, np:
sh -xv
W trakcie działania powłoki poleceniem wbudowanym set:
set -xv
Aby opcję wyłączyć, należy podać po niej znak +:
set -x+
Powłoka ma następujące opcje:
-c tekst
powoduje wykonanie pojedynczego polecenia, podanego za opcją. Nie można
jej ustawić poleceniem set.
-r
wywołanie powłoki okrojonej
-s
polecenia są czytane z wejścia standardowego
-e
zakończenie powłoki, jeśli wystąpi błąd przy wykonaniu polecenia
-f
zablokowanie rozwijania nazw plików
-n
polecenia są tylko czytane, nie są wykonywane. Służy do uruchamiania
skryptów
-u
traktowanie jako błędu użycia niezdefiniowanej zmiennej. Normalnie wstawiany
jest łańcuch pusty
-v
wyświetlanie wierszy poleceń po ich przeczytaniu
-x
wyświetlenie wierszy poleceń przed wykonaniem (opcje -xv umożliwiają
obejrzenie, jak działa substytucja)
--
znak - jest argumentem, nie opcją.
24
Ćwiczenia
Zadanie 1.
Skopiuj nast. fragment skryptu:
if test $# -gt 3
then
echo ‘za duzo parametrow’
exit 1
else
if test –f $1
then
echo “S1 jest plikiem “
plik=$1
echo „nazwa pliku to $plik”
exit 2
else
if test –d $1
then
echo “ $1 jest katalogiem”
katalog=$1
exit 3
fi
fi
fi
Zauważmy, że każda otwarta instrukcja if musi mieć swój odpowiednik zakończenia w
postaci „fi”.
Następnie zmień uprawnienia przy użyciu polecenia chmod, nadając prawa do wykonania
skryptu. Wywołaj kolejno skrypt z jednym, dwoma, trzema i 4 parametrami. Zapisz rezultaty.
Zadanie 2
Utwórz nowy skrypt:
if test $# -eq 1
then
{
if test –d $1
then
{
echo "podany argument jest katalogiem"
echo "katalog roboczy to $1"
katalog=$1
}
else
{
echo "to nie katalog – blad!!!!"
exit
25
}
fi
}
else
if test $# -gt 1
then
{
echo "za duzo argumentow"
exit
}
else
{
katalog=`pwd`
echo "katalog roboczy to $katalog"
}
fi
fi
Pytanie:
Co oznacza konstrukcja:
katalog=`pwd`
Zmień uprawnienia i wytestuj, używając odpowiednich argumentów wywołania.