1.4 Werken in de terminal

Waar je bent, waar je heen wil, en hoe je een programma bewaart

OpmerkingLeerdoelen

Na deze les kan je:

  • de bouw van een commando aanwijzen: de naam, de opties en de argumenten
  • het bestandssysteem beschrijven als een boom en een pad erin lezen
  • je verplaatsen met pwd, ls en cd
  • een map maken, een bestand schrijven in micro en het uitvoeren met python3
  • kopiëren, hernoemen en weggooien met cp, mv, rm en rmdir, en uitleggen waarom weggooien hier definitief is
  • tab-aanvulling en de pijl omhoog gebruiken om minder te typen

We gebruiken als programmeeromgeving een Linux virtuele machine op een Chromebook. Je bedient hem niet met knoppen maar met getypte commando’s. Het venster waarin je typt heet de terminal. Het programma daarbinnen dat je commando’s leest en uitvoert, heet de shell. Deze les leert je de eerste stappen om ermee te kunnen werken.

1 Om je van de eerste schrik te verlossen

Een regel in een terminal ziet eruit als geheimschrift. Dat is het niet. Elk commando dat je ooit zal typen heeft dezelfde bouw, met drie plaatsen in een vaste volgorde: eerst de naam, dan de opties, dan de argumenten. De naam zegt wat er moet gebeuren, de opties zeggen hoe, en de argumenten zeggen waarop.

ls        -l      /home/leerling
micro             oefening1.py
python3           oefening1.py
cd                oefeningen

Drie van die vier hebben geen enkele optie. Dat hoeft ook niet, dan gebeurt gewoon het basisgeval.

Een optie herken je aan het streepje. Eén streepje hoort bij een letter, zoals -h, twee streepjes bij een woord, zoals --help.

De drie plaatsen worden gescheiden door spaties. Een bestand met een spatie in zijn naam zorgt dus voor problemen: de shell telt er twee argumenten in plaats van één.

En daarmee kan je een commando lezen dat je nooit eerder zag. Wat qpdf --decrypt --linearize rapport_oud.pdf rapport_nieuw.pdf precies doet weet je niet, maar je ziet een naam, twee opties en twee bestanden.

2 Het bestandssysteem is een boom

Alle bestanden en mappen samen vormen één boom. Bovenaan staat één map waar al de rest onder valt, en die heet de root. Je schrijft hem als /. Elke map kan mappen en bestanden bevatten. Een bestand bevat geen mappen en is dus altijd een blad, een punt waar de boom ophoudt.

/
├── etc
├── home
│   └── leerling
│       ├── iw6
│       │   ├── data.csv
│       │   └── oefeningen
│       │       └── oefening1.py
│       └── notities.txt
└── usr

flowchart TD
    root["/"] --> etc["etc"]
    root --> home["home"]
    root --> usr["usr"]
    home --> leerling["leerling"]
    leerling --> iw6["iw6"]
    leerling --> notities(["notities.txt"])
    iw6 --> data(["data.csv"])
    iw6 --> oefeningen["oefeningen"]
    oefeningen --> oefening1(["oefening1.py"])

In plaats van leerling staat daar jouw eigen gebruikersnaam.

De map met jouw naam is je thuismap. Daar staat jouw werk, en daar begin je telkens als je de terminal opent. Omdat je die map voortdurend nodig hebt, bestaat er een afkorting voor: ~.

Een pad is een route door de boom, met / tussen de stappen. Er zijn twee manieren om er een te schrijven. Een pad dat begint met / vertrekt bij de root en wijst altijd dezelfde plaats aan, waar je ook staat. Een pad dat daar niet mee begint, vertrekt bij de map waar je op dit moment staat.

Twee namen komen in elk pad terug. . is de map waar je staat, en .. is de map één stap hoger.

Een boom heeft een eigenschap die dit alles eenvoudig maakt. Tussen twee punten in een boom bestaat er precies één weg. Niet nul, want alles is met dezelfde root verbonden, en niet twee, want dan zat er een lus in en was het geen boom meer. Daarom volstaat het te weten waar je bent en waar je heen wil. De enige mogelijke route ligt per definitie vast.

3 Waar je bent en waar je heen gaat

Drie commando’s volstaan. Hun namen lijken geheimschrift en zijn het niet: het zijn afgekorte Engelse woorden.

pwd staat voor print working directory en zegt in welke map je staat. Je werkmap, met andere woorden.

leerling@penguin:~$ pwd
/home/leerling

De eerste regel is wat jij typte, de tweede wat pwd antwoordde. Wat ervoor staat, leerling@penguin:~$, heet de prompt. Die zet de shell er zelf bij, om te zeggen dat het jouw beurt is. Je leest er je gebruikersnaam in, de naam van de machine, en de map waar je staat. Achter de $ begint wat jij typt.

ls staat voor list en toont wat er in die map staat.

leerling@penguin:~$ ls
iw6  notities.txt

Staat er niets in de map, dan toont ls niets. Dat is geen fout. Er zijn immers twee soorten commando’s. pwd en ls zijn er om iets te tonen, en die antwoorden dus altijd, ook al is het antwoord soms leeg. Andere commando’s zijn er om iets te doen, en die zwijgen als het lukt: je krijgt gewoon een nieuwe prompt. Zie je bij zo’n commando toch een regel verschijnen, dan is er iets misgelopen.

cd staat voor change directory en verplaatst je.

leerling@penguin:~$ cd iw6
leerling@penguin:~/iw6$ pwd
/home/leerling/iw6

Merk op dat de prompt zelf meeverandert en toont waar je staat. cd .. brengt je een stap omhoog, en cd zonder argument brengt je in één keer terug naar je thuismap.

BelangrijkBelangrijk

Een commando werkt op de map waar je staat, tenzij je er een pad bij geeft. ls toont hier, ls /etc toont daar. Wie een bestand niet terugvindt, staat meestal ergens anders dan gedacht. pwd is dan het eerste wat je typt.

4 Een map maken, een bestand schrijven, en het uitvoeren

mkdir staat voor make directory. Je geeft de naam van de nieuwe map mee als argument.

leerling@penguin:~$ mkdir iw6
leerling@penguin:~$ cd iw6
leerling@penguin:~/iw6$ mkdir oefeningen
leerling@penguin:~/iw6$

De tweede mkdir maakt oefeningen binnen iw6, want dat is de map waar je op dat moment staat.

Om een bestand te schrijven gebruik je micro, een teksteditor die in de terminal draait. Die staat nog niet op je machine, dus haal je hem eerst binnen. Dat doe je één keer.

leerling@penguin:~/iw6$ sudo apt install micro

apt is het programma dat software installeert en bijwerkt, en sudo ervoor zegt dat het commando met beheerdersrechten moet lopen. Dat is nodig omdat installeren het hele systeem raakt en niet enkel jouw thuismap. Die beheerder heet zelf root, dezelfde naam als de bovenste map, en het is die tweede betekenis die meespeelt bij het rooten van een gsm: niet de map, maar de rechten.

Daarna geef je micro de naam van het bestand mee. Bestaat het nog niet, dan maakt micro het aan.

leerling@penguin:~/iw6$ micro oefeningen/oefening1.py

Je typt je code zoals in eender welke editor. Ctrl-S bewaart en Ctrl-Q sluit af. Daarna sta je terug in de terminal.

Een Pythonbestand voer je uit door python3 het bestand als argument te geven.

leerling@penguin:~/iw6$ python3 oefeningen/oefening1.py
Hallo

Zit er een fout in, dan krijg je een foutmelding met het bestand, het regelnummer en het stuk van de regel erbij.

leerling@penguin:~/iw6$ python3 oefeningen/oefening1.py
Traceback (most recent call last):
  File "/home/leerling/iw6/oefeningen/oefening1.py", line 1, in <module>
    print(naam)
          ^^^^
NameError: name 'naam' is not defined

Dat is meer dan een cel op deze site je geeft. Je weet welk bestand, welke regel, en welk stuk van die regel.

5 Kopiëren, hernoemen en weggooien

Wat je maakt, wil je vroeg of laat ook kopiëren, een andere naam geven of weggooien. Daarvoor zijn er vier commando’s, en er hoort één waarschuwing bij alle vier: de terminal heeft geen Prullenbak. Wat je hier weggooit is weg, en staat ook niet in de prullenbak van de Bestanden-app.

cp staat voor copy en maakt een kopie. Je geeft eerst het bestand mee dat je kopieert, dan de naam die de kopie moet krijgen.

leerling@penguin:~/iw6$ cp oefeningen/oefening1.py oefeningen/oefening1.py.bak

De extensie .bak komt van backup. Programmeurs zetten ze achter een naam om aan te geven dat het een reservekopie is, en in ls zie je dat dan meteen terug. De shell behandelt zo’n bestand als elk ander, maar doordat de naam op .bak eindigt en niet meer op .py, voer je de kopie ook niet per ongeluk uit.

Dat is meteen het enige ongedaan maken dat je zelf in handen hebt. Ga je iets uitproberen waarvan je niet zeker bent, maak dan eerst een kopie. Loopt het mis, dan zet je de kopie terug.

mv staat voor move en verplaatst een bestand. Hernoemen doe je met hetzelfde commando, want de naam van een bestand is meteen zijn plaats in de boom. Wie hernoemt, verplaatst dus binnen dezelfde map.

leerling@penguin:~/iw6$ mv oefeningen/oefening1.py.bak oefeningen/kopie.py
leerling@penguin:~/iw6$ mv oefeningen/kopie.py .

De eerste regel hernoemt, de tweede verplaatst de kopie naar iw6, de map waar je staat. Het is tweemaal hetzelfde commando.

WaarschuwingOpgelet

Bestaat de naam die je als bestemming opgeeft al, dan overschrijven mv en cp dat bestand zonder iets te vragen. Je krijgt geen waarschuwing en geen uitvoer, enkel een nieuwe prompt, en de vorige inhoud is weg. Kijk met ls na of de naam die je kiest nog vrij is.

rm staat voor remove en gooit een bestand weg.

leerling@penguin:~/iw6$ rm kopie.py

Op een map werkt dat niet.

leerling@penguin:~/iw6$ rm oefeningen
rm: cannot remove 'oefeningen': Is a directory

rmdir staat voor remove directory en gooit een map weg, maar enkel als er niets meer in staat.

leerling@penguin:~/iw6$ rmdir oefeningen
rmdir: failed to remove 'oefeningen': Directory not empty

Twee weigeringen dus, en ze staan er met opzet. Ze houden tegen dat één verkeerd getypt argument een volledige map meeneemt.

Wil je een map met inhoud en al weg, dan voeg je bij rm de optie -r toe, van recursive, waarmee het commando de map en alles wat erin zit doorloopt.

leerling@penguin:~/iw6$ rm -r oud

Daarmee valt de weigering weg, en je vangnet dus ook. Typ eerst ls oud, zodat je ziet wat je meeneemt. Dat kost één commando.

Tot slot is er één ding op deze pagina dat je wel ongedaan kan maken. cd - brengt je terug naar de map waar je daarvoor stond, en toont welke dat is.

leerling@penguin:~/iw6$ cd /etc
leerling@penguin:/etc$ cd -
/home/leerling/iw6
leerling@penguin:~/iw6$

Dat is meteen de uitzondering op de stilte uit sectie 3: cd - doet iets én zegt iets, omdat je anders niet weet waar je belandt.

6 Zelf verder zoeken

Je kent nu tien commando’s. Er bestaan er duizenden, en niemand kent die uit het hoofd. Wat je wel hoort te kunnen, is uitzoeken hoe iets werkt.

Een taalmodel kent deze commando’s grondig. Ze bestaan al meer dan vijftig jaar, ze staan in ontelbare handleidingen, en ze veranderen nauwelijks. Vraag het wel precies. Zeg wat je wil bereiken, in welke map je staat, en hoe je bestanden heten. “Hoe verwijder ik een map” levert een ander antwoord dan “hoe verwijder ik de map oefeningen in mijn thuismap, met alles wat erin staat”.

Dat botst niet met wat het voorwoord zegt over taalmodellen. Daar gaat het over oefeningen, die er staan om na te gaan of je iets zelf kan. Een commando opzoeken is dat niet. Het commando is je gereedschap, niet de opgave.

Onder programmeurs is man <commando> het klassieke naslagwerk. Het toont de volledige handleiding, geschreven voor wie al weet waar hij naar zoekt, en het staat op zowat elke Linuxmachine. Op deze is het niet geïnstalleerd, en je zal het waarschijnlijk nooit missen.

Online staat er over deze commando’s meer geschreven dan over eender welke programmeertaal. Elke foutmelding die jij krijgt, kreeg iemand anders al.

En daar zit meteen de reden waarom je dit in een terminal leert en niet in een app die programmeren aanleert. Dit is geen omgeving die voor de les bedacht werd en die ophoudt te bestaan als een abonnement afloopt. De shell, de mappenboom en deze commando’s liggen onder het grootste deel van het internet, onder de servers waarop websites draaien, en onder heel wat programma’s met knoppen die je dagelijks gebruikt. Ze staan er al een halve eeuw, en er is niets dat erop wijst dat daar snel verandering in komt.

7 Minder typen

Twee toetsen halen het meeste werk weg.

Met tab vult de shell aan. Typ je cd iw en druk je tab, dan maakt hij daar cd iw6/ van. Past er meer dan één naam bij wat je typte, dan gebeurt er niets bij de eerste druk en toont hij bij de tweede alle mogelijkheden. Tab werkt op commando’s, op mapnamen en op bestandsnamen.

Met de pijl omhoog haal je vorige commando’s terug. Eén keer drukken geeft het laatste, nog eens drukken het commando daarvoor. Je kan het aanpassen voor je enter drukt. Bij het herhaaldelijk uitvoeren van hetzelfde programma scheelt dat elke keer een volledige regel.

Wie deze twee gebruikt typt minder en maakt minder typfouten. Tab is meteen ook een controle: vult hij niet aan, dan bestaat wat je typte niet.

8 Conclusie

Een commando bestaat uit een naam, opties en argumenten, in die volgorde. Het bestandssysteem is een boom met / als root, en een pad is een route erin. Je thuismap is ~, de map waar je staat is . en één stap hoger is ... Met pwd, ls en cd weet je waar je staat en raak je waar je wil zijn. Met mkdir, micro en python3 maak je een plaats, schrijf je er een programma en voer je het uit. Met cp, mv, rm en rmdir kopieer, hernoem en verwijder je, en dat laatste kan je niet ongedaan maken. Stilte betekent dat het gelukt is.

9 Begrippen

  • terminal (terminal): het venster waarin je typt en waarin de uitvoer verschijnt.
  • shell (shell): het programma in de terminal dat je commando’s leest en uitvoert.
  • commando (command): een opdracht aan de computer, bestaande uit een naam, eventuele opties en eventuele argumenten.
  • optie (option, flag): een aanpassing van wat een commando doet, herkenbaar aan een streepje, zoals -l.
  • argument (argument): datgene waarop een commando werkt, meestal een bestand of een map.
  • prompt (prompt): wat de shell vooraan de regel zet om aan te geven dat het jouw beurt is, hier leerling@penguin:~$.
  • map (directory, folder): een plaats in de boom die bestanden en andere mappen kan bevatten.
  • bestand (file): een stuk bewaarde inhoud, dat zelf niets bevat.
  • boom (tree): de structuur van alle mappen en bestanden samen, waarbij alles onder één root valt en er tussen twee punten precies één weg bestaat.
  • root: de bovenste map, geschreven als /.
  • blad (leaf): een punt in de boom waar niets meer onder zit. Elk bestand is een blad.
  • thuismap (home directory): de map die van jou is, afgekort als ~.
  • pad (path): een route door de boom, met / tussen de stappen.
  • werkmap (working directory): de map waar je op dit moment staat.

10 Oefeningen

  1. Open een terminal en typ pwd. In welke map sta je? Schrijf het pad op.

/home/ gevolgd door je eigen gebruikersnaam. Dat is je thuismap, en daar begin je altijd.

  1. Wijs in ls -l /etc het commando, de optie en het argument aan.

ls is het commando, -l is de optie en /etc is het argument.

  1. Maak een map iw6 in je thuismap, ga erin, maak daarin een map oefeningen, en controleer met pwd waar je staat.
leerling@penguin:~$ mkdir iw6
leerling@penguin:~$ cd iw6
leerling@penguin:~/iw6$ mkdir oefeningen
leerling@penguin:~/iw6$ pwd
/home/leerling/iw6

pwd toont /home/leerling/iw6, want mkdir verplaatst je niet.

  1. Je staat in /home/leerling/iw6. Schrijf twee verschillende commando’s die je naar je thuismap brengen.

cd .. gaat één stap omhoog, en dat is hier je thuismap. cd zonder argument doet hetzelfde, en cd ~ en cd /home/leerling eveneens.

  1. Schrijf in je map oefeningen een bestand oefening1.py dat Hallo toont, en voer het uit.
leerling@penguin:~/iw6$ micro oefeningen/oefening1.py
leerling@penguin:~/iw6$ python3 oefeningen/oefening1.py
Hallo

In micro typ je één regel, print("Hallo"), en je bewaart met Ctrl-S en sluit af met Ctrl-Q.

  1. Verwijder het sluitende haakje uit oefening1.py en voer het opnieuw uit. Vergelijk de foutmelding met die uit sectie 4. Wat is er anders, en waarom?
leerling@penguin:~/iw6$ python3 oefeningen/oefening1.py
  File "/home/leerling/iw6/oefeningen/oefening1.py", line 1
    print("Hallo"
         ^
SyntaxError: '(' was never closed

Er staat geen Traceback boven. Python leest een bestand eerst volledig na op schrijffouten, en pas als dat lukt voert hij het uit. Deze fout werd dus gevonden voor er iets uitgevoerd werd, en er is geen uitvoering om te tonen. De melding zegt wel precies wat er scheelt.

  1. Typ cd ie en druk op tab. Wat gebeurt er, en waarom?

Er gebeurt niets, want er is geen map die met ie begint. Tab kan enkel aanvullen wat bestaat, en dat maakt hem meteen een controle op typfouten.

  1. Teken de boom uit sectie 2 opnieuw, maar met jouw eigen mappen erin. Gebruik ls in je thuismap om te zien wat er staat.

Er is geen één juist antwoord. Je thuismap zit in /home, en wat jij zelf aanmaakte zit daarin.