15. Combineren, redirection en pipes
Combineren van opdrachten
Tot nu toe hebben we steeds één opdracht per "regel" ingevoerd
(behalve bij bv. nice, maar dat is een uitzondering op de regel).
Het is echter mogelijk meerdere opdrachten achter elkaar op één
regel te geven. De verschillende opdrachten moeten dan van elkaar gescheiden
worden door een punt-komma (;). Een voorbeeld:
[jan@gnodde linux]$ cd ..; ls; pwd
jan klaas linux marie test
/home
[jan@gnodde home]$
De verschillende opdrachten worden netjes na elkaar uitgevoerd.
Splitsen
Een opdracht kan, bv. door zo'n combinatie, soms erg lang worden. Dan is het
mogelijk ze over meerdere regels te verdelen. Dat kan met behulp van de
backslash (\):
[jan@gnodde linux]$ cd ..;\
> ls;\
> pwd\
> cd
jan klaas linux marie test
/home
[jan@gnodde linux]$
Pas na de enter op een regel die niet eindigt op een backslash, worden de
opdrachten achter elkaar uitgevoerd.
Redirection
Normaal gesproken komt de uitvoer van een Linux-opdracht (bv. ls) op
het beeldscherm terecht. Dat komt omdat, normaal gesproken, voor Linux het
beeldscherm het standaard uitvoerkanaal is (stdout). Het heeft zelfs
een kanaalnummer, en wel 1.
Het toetsenbord is meestal de standaardinvoer (stdin), kanaalnummer
0.
Er bestaat echter nog een kanaal: het standaardfout-kanaal (stderr),
nummer 2. Dit kanaal voert meestal ook naar het beeldscherm, zoals
je gemerkt zult hebben, als je weer eens een type-fout hebt gemaakt...
Stel nu, dat je de uitvoer van een opdracht niet op het beeldscherm, maar in
een bestand wilt hebben. Dat kan met een zgn. redirection: je
vertelt Linux, dat de uitvoer niet naar het beeldscherm moet, maar naar een
bepaald bestand. Een voorbeeld:
[jan@gnodde linux]$ ls /home
jan klaas linux marie test
[jan@gnodde linux]$ ls /home > uitvoer
[jan@gnodde linux]$
D.m.v. dat "pijltje" (>) geef je aan, dat de uitvoer van de opdracht
ls /home niet naar de standaarduitvoer (stdout) moet, maar
naar een bestand met de naam uitvoer. Het bestand
uitvoer hoeft niet te bestaan: het wordt door deze opdracht
gemaakt. Nog erger: als het bestand al wèl bestaan zou hebben, zou het
nu overgeschreven zijn!
Je kunt de inhoud van uitvoer bekijken met bv. cat
uitvoer, en je zult zien dat daar staat, wat anders op het scherm zou
staan.
Als je wilt, dat de uitvoer van een opdracht wordt toegevoegd aan een
bestaand bestand (dus niet zomaar overschrijven), dan gebruik je een dubbel
"pijltje" (>>):
[jan@gnodde linux]$ ls /etc >> uitvoer
[jan@gnodde linux]$
Effe tjsekke met cat uitvoer of less uitvoer en je zult
zien, dat achter de oorspronkelijke tekst de uitvoer van ls /etc
geplakt zit.
Mocht trouwens het genoemde bestand toch niet bestaan, dan wordt het ook
alsnog aangemaakt.
Bestanden plakken
Je kunt meerdere bestanden samenvoegen in één bestand op de
volgende wijze:
[jan@gnodde linux]$ cat bestand1 > grootbestand
[jan@gnodde linux]$ cat bestand2 >> grootbestand
[jan@gnodde linux]$ cat bestand3 >> grootbestand
[jan@gnodde linux]$
Het kan echter eenvoudiger, in slechts één regeltje, met
cat bestand1 bestand2 bestand3 > grootbestand
Je zou dit kunnen gebruiken in combinatie met split: een groot
bestand van, bv., 3,9Mb kun je splitsen in 3 bestanden van ieder 1,3Mb, zodat
ze elk op een floppy passen. Na ze, met de benenwagen, naar computer nr.2
overgebracht te hebben kun je de deel-bestanden d.m.v. bovenstaand voorbeeld
weer samenvoegen tot het originele grote bestand. Het is maar dat je het
weet...
Redirection van invoer
Als een programma input van een gebruiker nodig heeft, komt dat meestal van
het toetsenbord (stdin). De Linux-opdracht tr verwacht z'n
input bv. op deze manier. Als je het artikel over tekstgereedschappen
bestudeerd hebt, weet je echter, dat er ook een andere manier is, om een
programma van input te voorzien, nl. d.m.v. redirection. Om het programma
tr nog maar eens te gebruiken: als je van een bestand alle kleine
letters wilt veranderen in hoofdletters kun je dat bestand d.m.v. redirection
naar tr sturen:
tr "[:lower:]" "[:upper:]" < bestand
tr krijgt zijn input dus nu niet van het toetsenbord, maar van het
bestand bestand. Het input-bestand zelf wordt door deze redirection
niet veranderd: het resultaat komt op het beeldscherm.
Combineren van input- en outputredirection
Als je, bij gebruik van het vorige voorbeeld, liever de output naar een
bestand ziet gaan dan naar het beeldscherm, kun je de redirection van input
en output zelfs combineren:
tr "[:lower:]" "[:upper:]" < bestand1 > bestand2
Alle letters van bestand1 zullen omgezet worden naar hoofdletters en
het resultaat wordt naar bestand2 geschreven. Zo zie je, dat je met
al die leuke kleine Linux-programmaatjes echt heel leuke dingen kunt doen. Je
wordt slechts beperkt door de grenzen van je fantasie!
Piping
Stel: je wilt weten hoeveel bestanden er in een bepaalde directory voorkomen.
Dan zou je een ls kunnen doen en gewoon het aantal bestanden tellen.
Maar als dat heel veel bestanden zijn, is dat lastig. Een leuke manier zou
zijn, om de output van ls naar een (tijdelijk) bestand te
"redirecten" en dan met wc het aantal woorden, en dus bestanden, te
tellen:
ls > /tmp/teller
wc < /tmp/teller
Je zult zien: dat lukt prima. Maar het kan nog makkelijker. Bij voorgaand
voorbeeld gebruikten we een (tijdelijk) bestand als tussenstation. D.m.v.
piping kan dit tussenstation overgeslagen worden. Je kunt de uitvoer van de
ene opdracht rechtstreeks doorgeven aan een tweede opdracht:
ls | wc
Nog een voorbeeld: stel, dat er in een bepaalde directory een flink aantal
mp3-bestanden staan, tussen nog weer andere bestanden. En je wilt
even een mooi alfabetisch overzicht van die mp3-bestanden hebben.
Dat kan heel eenvoudig:
ls | grep 'mp3' | sort
Hela! Een dubbele pipe...: ls geeft een overzicht van alle bestanden
in je directory, grep 'mp3' filtert daar de bestanden uit, waar de
tekst mp3 in voorkomt, en sort zet ze dan netjes op
alfabetische volgorde. Handig, hè?
Redirection van stderr
In het artikel over het zoeken van bestanden kwamen we de opdracht
find tegen. Als je, als gewoon gebruiker, deze opdracht gebruikt en
hij komt directories tegen, waar je niet in mag, dan krijg je foutmeldingen
op je beeldscherm. Probeer maar eens
find / -name mkfontdir
In Linux lopen foutmeldingen door kanaal 2 (stderr). Deze komen
meestal op je beeldscherm terecht. Je kunt echter deze foutmeldingen
redirecten, bv. door
find / -name mkfontdir 2>/dev/null
Hiermee redirect je de foutmeldingen naar het device /dev/null, en
dat is niets anders dan een zwart gat, een bodemloze put. Alles, wat je naar
/dev/null stuurt, verdwijnt in het niets! Dus ook onze
foutmeldingen.
Nu is het niet altijd handig om foutmeldingen te laten verdwijnen. Je kunt ze
dus ook redirecten naar een (log-)bestand, of ze er met >> aan vast
plakken.
Als je zowel de "normale" output als de foutmeldingen naar ieder een eigen
bestand wilt redirecten, dan kan dat als volgt (voorbeeld):
ls > bestand 2 > foutbestand
Het is echter ook mogelijk beide naar hetzelfde bestand te sturen:
ls > bestand 2>&1
Nieuw is hier de notatie 2>&1. Het betekent, dat de meldingen van
kanaal 2 (stderr) naar dezelfde plaats gestuurd worden als de
meldingen van kanaal 1 (stdout)
Inline input
Vaak is het nogal bewerkelijk om, als je een klein tekstje in een bestand
wilt zetten, apart je tekstverwerker op te starten (zelfs al is het
vi...). Er is echter een handige manier om dit snel op te lossen. We
maken hier gebruik van het feit, dat de opdracht cat, als er geen
bestand als argument opgegeven wordt, z'n input neemt van het
toetsenbord:
[jan@gnodde linux]$ cat > bestand
Dit is de tekst die ik kwijt
wil in het bestand "bestand"
^D
[jan@gnodde linux]$
cat leest de input van het toetsenbord, tot er een "EndOfFile"-teken
gegeven wordt. Dat "EOF"-teken is Ctrl-D (hierboven omschreven als
^D). De output van cat redirecten we naar bestand.
Je kunt het resultaat controleren met cat bestand.
Slot
De hier beschreven materie wordt in Linux-kringen veel gebruikt. Kijk maar
eens in wat shell-scripts in de /etc-directory.
Eén voordeel van dit artikel: je hoeft er de man-pages niet voor op te
slaan: we hebben geen specifieke Linux programma's behandeld.
Laatst herzien op 18-12-2006
|