Laboratorul 1: Linia de comandă, Sistemul de fișiere¶
Ierarhie¶
În sistemele de operare de tip UNIX fișierele și directoarele sunt organizate într-o structură arborescentă. Rădăcina este notată cu / și se mai numește și root. În rădăcină se găsesc mai multe directoare și fișiere. La rândul lor, aceste directoare pot conține alte fișiere și directoare. Directoarele dintr-un director se mai numesc și subdirectoare, subliniind relația ierarhică.
De exemplu, lista conturilor de utilizator se găsește în fișierul /etc/passwd. Acesta se află în directorul etc, care se află în rădăcină. Un exemplu cu mai multe niveluri este /usr/bin/ls, executabilul comenzii ls: fișierul ls se află în directorul bin, care se află la rândul său în directorul usr, care se află în rădăcină.
Un șir precum /usr/bin/ls se numește calea fișierului: numele directoarelor parcurse pornind de la rădăcină, separate prin /. O cale care începe cu / este o cale absolută și desemnează același fișier indiferent unde vă aflați în sistem. O cale care nu începe cu / este o cale relativă și este interpretată pornind de la directorul curent, adică directorul în care lucrați la un moment dat (vezi secțiunea Navigare). De exemplu, dacă directorul curent este /usr, calea relativă bin/ls desemnează același fișier ca și calea absolută /usr/bin/ls. Dacă însă directorul curent este /etc, aceeași cale relativă bin/ls desemnează /etc/bin/ls, care nu există.
Două nume speciale există în orice director: . reprezintă directorul însuși, iar .. directorul părinte. Astfel, dacă directorul curent este /usr/bin, calea ./ls desemnează /usr/bin/ls, iar calea ../lib desemnează /usr/lib.
Linia de comandă¶
Majoritatea comenzilor vor fi executate în cadrul unui terminal (ex. xterm(1), GNOME Terminal etc.). Deși dificil și aparent mai complicat la început, folosirea terminalului oferă multe avantaje precum flexibilitate, automatizarea sarcinilor și control la distanță al altor mașini.
Un terminal tipic are la bază un program de tip shell (ex. bash(1), ksh, zsh) care gestionează și execută comenzi secvențial sau în paralel. Promptul unui terminal indică faptul că se așteaptă o comandă de la utilizator și este în cea mai simplă formă constituit din simbolul $ sau % pentru utilizatorii comuni și # pentru administrator (denumit root în UNIX).
Tot ce este scris în dreapta promptului reprezintă comanda utilizatorului către mașină.
În exemplul de mai sus a fost executată comanda echo cu parametrul "Hello, World!". Rezultatul comenzii, dacă există, este afișat fără a fi prefixat cu prompt. Încheierea comenzii este semnalată prin reaparitia promptului.
De fiecare dată când vedeți o comandă necunoscută citiți manualul pentru a afla ce face:
Din motive istorice, manualul sistemului de operare (ce include manualele comenzilor) este împărțit în secțiuni. Astfel pot exista mai multe intrări cu același nume dar în secțiuni diferite. Vezi cunoscuta funcție printf.
Prima instrucțiune s-ar putea să vă surprindă afișând manualul comenzii printf nu a funcției C printf. Comenzile de terminal se află de regulă în secțiunea 1, pe când funcțiile se află în secțiunea 3. Pentru a accesa manualul funcției trebuie să specificăm un argument în plus comenzii man(1) care specifică secțiunea explicit. Din această cauză când ne referim la o comandă sau o funcție punem la sfârșit și secțiunea din manual în care este documentată: printf(1) versus printf(3). Este bine de știut că există manual și pentru comanda de citit manuale:
În interiorul unei pagini de manual vă deplasați cu săgețile sau cu Space (o pagină întreagă), căutați un cuvânt cu /, treceți la următoarea potrivire cu n și ieșiți cu q:

Lucrul eficient în linia de comandă¶
Câteva combinații de taste vă scutesc de mult timp și de multe greșeli în terminal:
| Tastă | Efect |
|---|---|
Tab |
completează numele comenzii sau al fișierului început |
↑ / ↓ |
parcurge comenzile introduse anterior |
Ctrl+C |
întrerupe comanda aflată în execuție |
Când există o singură potrivire, Tab completează direct numele. Când există mai multe, apăsați Tab de două ori pentru a vedea variantele, apoi mai tastați câteva litere:

Cu ↑ puteți readuce o comandă anterioară și o puteți modifica înainte de a o rula din nou:

Pentru a exersa Ctrl+C, rulați:
Comanda sleep(1) așteaptă 100 de secunde fără să afișeze nimic, iar promptul nu reapare până la încheierea ei. Apăsați Ctrl+C pentru a o opri și a reveni la prompt. Același lucru îl puteți face cu orice comandă care durează prea mult sau pare blocată.

Copiere și lipire. Deoarece Ctrl+C întrerupe comenzi, în majoritatea terminalelor copierea și lipirea se fac cu Ctrl+Shift+C și Ctrl+Shift+V, sau din meniul deschis cu click dreapta. Atenție când copiați comenzi din acest document: simbolul $ de la începutul liniei este promptul și nu face parte din comandă, iar liniile fără $ sunt rezultatul afișat de comandă. Copiați doar comanda propriu-zisă.
Navigare¶
În general, fiecare utilizator are un spațiu de lucru propriu în care își poate desfășura activitatea. Acest spațiu este găzduit într-un director, de regulă /home/username, care este memorat în variabila $HOME.
Acest tip de variabilă se mai numește și variabilă de mediu. Ele sunt definite dinamic de sistem sau utilizator pentru a fi folosite de programe la execuție. Variabilele sunt în general scrise cu litere mari și precedate de simbolul $.
Shell-ul oferă și o prescurtare pentru directorul $HOME: caracterul ~ (tilda). Astfel, ~/Documents este echivalent cu $HOME/Documents, adică /home/horatiu/Documents în exemplul de mai sus.
Când este pornit un terminal, acesta de regulă vă plasează în directorul $HOME. Folosiți comanda pwd(1) pentru a verifica în orice moment unde vă aflați și comanda ls(1) pentru a lista conținutul directorului curent.
$ pwd
/home/horatiu/Documents/itbi/lab1
$ ls
itbi-lab-1.aux itbi-lab-1.fdb_latexmk itbi-lab-1.fls
itbi-lab-1.log itbi-lab-1.pdf itbi-lab-1.tex
Toate comenzile se execută relativ la directorul curent: ls(1) verifică implicit directorul curent și listează conținutul său.
Comportamentul unei comenzi poate fi modificat prin opțiuni, care de regulă încep cu -. De exemplu, opțiunea -l a comenzii ls(1) afișează detalii despre fiecare fișier:
Coloanele reprezintă, în ordine: tipul fișierului și permisiunile (discutate într-un laborator viitor), numărul de legături, proprietarul, grupul, dimensiunea în octeți, data ultimei modificări și numele. Primul caracter indică tipul: - pentru un fișier obișnuit și d pentru un director.
Fișierele și directoarele al căror nume începe cu . sunt ascunse: ls(1) nu le afișează implicit. De regulă acestea sunt fișiere de configurare, precum ~/.bashrc, pe care shell-ul bash îl citește la pornire. Pentru a le afișa folosiți opțiunea -a:
Rezultatul diferă de la un sistem la altul. Observați că în listă apar și intrările speciale . și .., descrise în secțiunea Ierarhie. Opțiunile pot fi și combinate: ls -la afișează detaliat toate fișierele, inclusiv pe cele ascunse.
Dacă doriți să schimbați directorul curent folosiți comanda cd(1). Aceasta primește ca parametru viitorul director curent. El poate fi dat relativ la directorul curent sau în formă absolută pornind de la rădăcină. Reamintim că .. desemnează directorul părinte. Deci dacă vrem din exemplul anterior să ajungem acasă putem folosi oricare dintre următoarele comenzi:
Implicit cd(1) fără argumente schimbă directorul în directorul $HOME.
Pentru a afla unde se află executabilul aferent unei comenzi folosiți comanda which(1):
O altă variabilă importantă este cea în care sunt memorate căile din sistemul de fișiere în care se găsesc executabilele.
În general, comanda pentru a rula un executabil este dată de calea (fie absolută, fie relativă la directorul curent) către acesta.
Calea absolută:
Calea relativă:
Observați că ls(1) se află într-unul din directoarele conținute în $PATH, motiv pentru care nu este nevoie să specificăm întreaga cale. Pentru a adăuga directoarele la $PATH se poate folosi comanda
pentru adăugare la final, sau
pentru adăugare la început.
Spre exemplu, după
toate executabilele din /home/horatiu/itbi/bin vor putea fi apelate drept comenzi cu numele lor.
Editarea textului în linia de comandă¶
Pentru editarea fișierelor din linia de comandă sunt disponibile diverse editoare fără interfață grafică, precum nano(1) sau vi(1).
În nano(1) scrieți direct textul, salvați cu Ctrl+O (confirmați numele fișierului cu Enter) și ieșiți cu Ctrl+X. Scurtăturile principale sunt afișate în partea de jos a ecranului, unde ^ înseamnă tasta Ctrl.

Un avantaj al acestora este că pot fi utilizate inclusiv pe sisteme care nu pun la dispoziție o interfață grafică. Desigur, multe distribuții vin cu editoare grafice instalate, precum gedit sau kate, care pot fi apelate într-o manieră similară.
Citire și scriere¶
Pentru a crea fișiere noi text se poate folosi echo(1):
unde operatorul > redirecționează ieșirea comenzii către fișierul foo. Dacă foo există, va fi suprascris. Pentru a adăuga la sfârșitul unui fișier existent folosiți >>. Fișierele text scurte pot fi rapid afișate în terminal cu ajutorul comenzii cat(1).
Deși se poate aplica aceeași comandă asupra fișierelor binare, precum executabilele, nu este recomandat deoarece anumite "caractere" rezultate pot fi interpretate de shell drept caractere de control care vor da peste cap funcționarea normală a terminalului.
Atunci când ieșirea unei comenzi este prea lungă și depășește lungimea terminalului, pentru a parcurge toată informația se recomandă folosirea unui pager precum less(1):
unde operatorul | se numește pipe. Un pipe transformă ieșirea programului din stânga în intrarea celui din dreapta. Pentru a ieși din less(1) apăsați tasta q. Pentru a căuta un text folosiți comanda /. De exemplu /print va căuta șirul de caractere print. Evident, less(1) poate fi folosit direct pentru a inspecta fișiere și este util mai ales pentru fișiere text mari:
Manipulare¶
Directoarele sunt create cu comanda mkdir(1):
Pentru a crea fișiere noi lipsite de conținut folosiți comanda touch(1).
Operarea de copiere se face cu comanda cp(1):
iar cea de mutare cu comanda mv(1):
Fișierele se șterg cu comanda rm(1), iar directoarele goale cu comanda rmdir(1):
Sarcini de laborator¶
-
Rulați toate comenzile descrise în laborator
-
Refaceți următoarea ierarhie de directoare și fișiere folosind comenzile
mkdir(1) șitouch(1): -
Creați un director și câteva fișiere în acesta. Încercați să ștergeți directorul creat folosind
rmsaurmdir. Ce observați? Căutați în manualulrm(1) cum să ștergeți recursiv și folosiți informația pentru a șterge într-o singură instrucțiune directorul creat devreme. -
Creați un director
binîn$HOMEși adăugați-l în$PATH. Copiați un executabil existent (de exemplugcc) și observați cum/dacă se modifică ieșirea comenziiwhich(1) când întrebați de executabilul copiat. Dacă nu se schimbă, de ce?