Tips en Trucs 2019

Opdrachtresultaten doorsturen voor verdere bewerking

De doorstuur (redirect) mogelijkheid zorgt dat je de uitvoer (resultaten) van opdrachten naar bestanden en apparaten kunt sturen. Maar het werkt ook omgekeerd, zo kunnen opdrachten invoer van apparaten en de inhoud van bestanden verwerken.

Virtuele bestanden

Alles in Linux verloopt via bestanden. Zo worden bij het uitvoeren van elk programma (opdracht) standaard drie bestanden gebruikt. Deze hebben een nummer en een naam:

Standaard worden stdout en stderr verbonden met het scherm. Waardoor de resultaten en foutmeldingen niet in een bestand worden opgeslagen, maar op het scherm verschijnen. De standaard invoer is verbonden met het toetsenbord en zorgt voor de te verwerken gegevens. Via redirection (doorsturen) kunnen we deze standaard associaties manipuleren.

Standaard uitvoer doorsturen

Standaard worden de resultaten van een opdracht of programma naar het scherm gestuurd (weergegeven). Het kan soms handig zijn om uitvoer (bijvoorbeeld in scripts) niet weer te geven, of in een bestand op te slaan. Dit kan met behulp van de > operator:

dany@pindabook:~> ls -l > uitvoer.txt

In het voorbeeld sturen we de uitvoer van de ls opdracht naar het bestand uitvoer.txt. Daarbij wordt indien nodig het bestand automatisch aangemaakt. Er verschijnt niets op het scherm, maar als we de inhoud van het bestand bekijken, zien we:

dany@pindabook:~> cat uitvoer.txt 
totaal 28
lrwxrwxrwx 1 dany users   33 28 mei  2018 Afbeeldingen -> /usr/home/Documents/Afbeeldingen/
drwxr-xr-x 2 dany users 4096 27 mei  2018 bin
drwxr-xr-x 2 dany users 4096 27 mei  2018 Bureaublad
lrwxrwxrwx 1 dany users   20 28 mei  2018 Documenten -> /usr/home/Documents/
drwxr-xr-x 2 dany users 4096  9 jan 10:39 Downloads
lrwxrwxrwx 1 dany users   27 28 mei  2018 Muziek -> /usr/home/Documents/Muziek/
drwxr-xr-x 3 dany users 4096  4 jan 18:38 Nextcloud
drwxr-xr-x 4 dany users 4096 28 mei  2018 onedrive
drwxr-xr-x 3 dany users 4096 28 mei  2018 OneDrive
lrwxrwxrwx 1 dany users   29 28 mei  2018 Openbaar -> /usr/home/Documents/Openbaar/
lrwxrwxrwx 1 dany users   30 28 mei  2018 Sjablonen -> /usr/home/Documents/Sjablonen/
-rw-r--r-- 1 dany users    0 11 jan 18:11 uitvoer.txt
lrwxrwxrwx 1 dany users   28 28 mei  2018 Video's -> /usr/home/Documents/Video's/
-rwxr-xr-x 1 dany users  896  3 jan 11:50 wallpaper.sh

M.a.w. het bestand bevat de uitvoer van de ls opdracht. Als we dezelfde opdracht opnieuw uitvoeren wordt de inhoud van het bestand uitvoer.txt overschreven met de uitvoer van de laatste opdracht. Om de reeds aanwezige inhoud van het bestand te behouden en aan te vullen met de uitvoer van een opdracht, gebruik je de >> operator:

dany@pindabook:~> ls -l >> uitvoer.txt

Indien het bestand uitvoer.txt niet bestaat, wordt het automatisch aangemaakt. Als het bestand uitvoer.txt wel bestaat (zoals in ons voorbeeld), wordt de uitvoer van de ls opdracht aan de bestaande inhoud van het bestand toegevoegd:

dany@pindabook:~> cat uitvoer.txt     
totaal 28
lrwxrwxrwx 1 dany users   33 28 mei  2018 Afbeeldingen -> /usr/home/Documents/Afbeeldingen/
drwxr-xr-x 2 dany users 4096 27 mei  2018 bin
drwxr-xr-x 2 dany users 4096 27 mei  2018 Bureaublad
lrwxrwxrwx 1 dany users   20 28 mei  2018 Documenten -> /usr/home/Documents/
drwxr-xr-x 2 dany users 4096  9 jan 10:39 Downloads
lrwxrwxrwx 1 dany users   27 28 mei  2018 Muziek -> /usr/home/Documents/Muziek/
drwxr-xr-x 3 dany users 4096  4 jan 18:38 Nextcloud
drwxr-xr-x 4 dany users 4096 28 mei  2018 onedrive
drwxr-xr-x 3 dany users 4096 28 mei  2018 OneDrive
lrwxrwxrwx 1 dany users   29 28 mei  2018 Openbaar -> /usr/home/Documents/Openbaar/
lrwxrwxrwx 1 dany users   30 28 mei  2018 Sjablonen -> /usr/home/Documents/Sjablonen/
-rw-r--r-- 1 dany users    0 11 jan 18:11 uitvoer.txt
lrwxrwxrwx 1 dany users   28 28 mei  2018 Video's -> /usr/home/Documents/Video's/
-rwxr-xr-x 1 dany users  896  3 jan 11:50 wallpaper.sh
totaal 32
lrwxrwxrwx 1 dany users   33 28 mei  2018 Afbeeldingen -> /usr/home/Documents/Afbeeldingen/
drwxr-xr-x 2 dany users 4096 27 mei  2018 bin
drwxr-xr-x 2 dany users 4096 27 mei  2018 Bureaublad
lrwxrwxrwx 1 dany users   20 28 mei  2018 Documenten -> /usr/home/Documents/
drwxr-xr-x 2 dany users 4096  9 jan 10:39 Downloads
lrwxrwxrwx 1 dany users   27 28 mei  2018 Muziek -> /usr/home/Documents/Muziek/
drwxr-xr-x 3 dany users 4096  4 jan 18:38 Nextcloud
drwxr-xr-x 4 dany users 4096 28 mei  2018 onedrive
drwxr-xr-x 3 dany users 4096 28 mei  2018 OneDrive
lrwxrwxrwx 1 dany users   29 28 mei  2018 Openbaar -> /usr/home/Documents/Openbaar/
lrwxrwxrwx 1 dany users   30 28 mei  2018 Sjablonen -> /usr/home/Documents/Sjablonen/
-rw-r--r-- 1 dany users  925 11 jan 18:11 uitvoer.txt
lrwxrwxrwx 1 dany users   28 28 mei  2018 Video's -> /usr/home/Documents/Video's/
-rwxr-xr-x 1 dany users  896  3 jan 11:50 wallpaper.sh

Je kunt de uitvoer van verschillende opdrachten groeperen door ze tussen accolades te plaatsen en dan door te sturen:

dany@pindabook:~> { echo "PindaNet"; ls -l; } > uitvoer.txt
dany@pindabook:~> cat uitvoer.txt 
PindaNet
totaal 32
lrwxrwxrwx 1 dany users   33 28 mei  2018 Afbeeldingen -> /usr/home/Documents/Afbeeldingen/
drwxr-xr-x 2 dany users 4096 27 mei  2018 bin
drwxr-xr-x 2 dany users 4096 27 mei  2018 Bureaublad
lrwxrwxrwx 1 dany users   20 28 mei  2018 Documenten -> /usr/home/Documents/
drwxr-xr-x 2 dany users 4096  9 jan 10:39 Downloads
lrwxrwxrwx 1 dany users   27 28 mei  2018 Muziek -> /usr/home/Documents/Muziek/
drwxr-xr-x 3 dany users 4096  4 jan 18:38 Nextcloud
drwxr-xr-x 4 dany users 4096 28 mei  2018 onedrive
drwxr-xr-x 3 dany users 4096 28 mei  2018 OneDrive
lrwxrwxrwx 1 dany users   29 28 mei  2018 Openbaar -> /usr/home/Documents/Openbaar/
lrwxrwxrwx 1 dany users   30 28 mei  2018 Sjablonen -> /usr/home/Documents/Sjablonen/
-rw-r--r-- 1 dany users    9 11 jan 18:28 uitvoer.txt
lrwxrwxrwx 1 dany users   28 28 mei  2018 Video's -> /usr/home/Documents/Video's/
-rwxr-xr-x 1 dany users  896  3 jan 11:50 wallpaper.sh

Het bestand uitvoer.txt bevat nu de tekst PindaNet en de uitvoer van de ls opdracht.

Om de uitvoer van een opdracht helemaal te negeren (in het niets laten verdwijnen) kan je deze naar een speciaal apparaat (device) sturen, namelijk /dev/null:

dany@pindabook:~> ls -l > /dev/null

Zowel standaard uitvoer als fouten doorsturen

In bovenstaande voorbeelden wordt de standaard uitvoer doorgestuurd. Bij het optreden van een fout, verschijnt de foutmelding nog steeds op het scherm:

dany@pindabook:~> ls -l onbestaande.bestand > /dev/null
ls: kan geen toegang krijgen tot 'onbestaande.bestand': Bestand of map bestaat niet

Dit komt doordat stderr en stdout twee totaal gescheiden virtuele bestanden zijn. Om zowel stdout als stderr naar een bestand door te sturen, bestaan verschillende oplossingen. De volgende oplossing werkt ook in oude opdrachtverwerkers (shells):

dany@pindabook:~> ls -l > uitvoer.txt 2>&1

Zoals daarstraks wordt de uitvoer van de ls opdracht naar het bestand uitvoer.txt gestuurd. Daarna sturen we de foutmeldingen (stderr) door naar de standaard uitvoer (stdout). Daarbij gebruiken we de referentienummers die bij de virtuele bestanden stdout en stderr horen. Modernere Bash versies kunnen ook de volgende oplossing gebruiken:

dany@pindabook:~> ls -l &> uitvoer.txt

Standaard uitvoer naar standaard fouten doorsturen

Bij het schrijven van scripts, wil je de gebruiker met behulp van een foutmelding wijzen op iets dat fout loopt. Met de echo opdracht kunnen we tekstberichten (de foutmelding) uitvoeren naar de standaard uitvoer om daarna het script te verlaten. Dit werkt perfect, maar eigenlijk behoort te 'foutmelding' naar stderr gestuurd te worden. De echo opdracht stuurt de foutmelding naar stdout, die we daarna afleiden naar stderr:

dany@pindabook:~> echo "Er is een fout opgetreden, script afgebroken!" >&2
Er is een fout opgetreden, script afgebroken!

Standaard invoer omleiden

Standaard komt de invoer van het toetsenbord, maar met de < operator kunnen de de invoer van ergens anders halen. De tr opdracht wordt gebruikt om tekens te verwijderen of te vervangen en werkt als volgt:

dany@pindabook:~> tr j e
Gojijdag!
Goeiedag!
^C

De tr opdracht zal alle ingevoerde j tekens vervangen door een e. Na het uitvoeren van de opdracht typ je op het toetsenbord Gojijdag!, gevolgd door Enter. Daarna verwerkt tr de ingevoerde tekst en kan je opnieuw tekst invoeren, enz. De opdracht stop je door Ctrl + c in te voeren. Om de tr opdracht van invoer uit een bestand te voorzien, maken we eerst een bestand aan met een tekst:

dany@pindabook:~> echo "Gojijdag!" > uitvoer.txt

De inhoud van het bestand uitvoer.txt laten we door tr verwerken:

dany@pindabook:~> tr j e < uitvoer.txt 
Goeiedag!

Pijpleidingen

Met behulp van een doorvoerbuis (pipe) (de | operator) kan je opdrachten aan elkaar knopen. De standaard uitvoer van de ene opdracht wordt daarmee als standaard invoer voor een andere opdracht gebruikt.

dany@pindabook:~> echo "Gojijdag!" | tr j e
Goeiedag!

De standaart uitvoer van de echo opdracht (bestaat uit de tekst Gojijdag!) wordt door de | (pipe) operator als standaard invoer aan de tr opdracht doorgegeven. Deze vervangt dan alle j-tekens door e-tekens.

Veronderstel dat je enkel de tekst tot de eerste d letter wilt weergeven:

dany@pindabook:~> echo "Gojijdag!" | tr j e | cut -f 1 -d 'd'
Goeie

We sturen hier de standaard uitvoer van de tr opdracht verder door naar de cut opdracht die de ingevoerde tekst afknipt bij de eerste letter d.

tee

De tee opdracht leest de standaard invoer en voert deze terug uit en slaat deze tegelijkertijd op in een bestand. Zo kan je een pijpleiding aftakken (T stuk). In het volgende voorbeeld wordt de tekst afkomstig van de tr opdracht in het bestand uitvoer.txt opgeslagen en doorgestuurd naar de cut opdracht:

dany@pindabook:~> echo "Gojijdag!" | tr j e | tee uitvoer.txt | cut -f 1 -d 'd'
Goeie
dany@pindabook:~> cat uitvoer.txt 
Goeiedag!

Op het scherm verandert er niets, maar het bestand uitvoer.txt bevat de standaard uitvoer van de tr opdracht.

In bepaalde omstandigheden is tee zeer handig. Om met de echo opdracht tekst in een bestand met root rechten op te slaan, gebeurt dit:

dany@pindabook:~> sudo touch beveiligd.txt
[sudo] wachtwoord voor root:
dany@pindabook:~> sudo echo "PindaNet" > beveiligd.txt
-bash: beveiligd.txt: Toegang geweigerd

De sudo zorgt ervoor dat de echo opdracht met root rechten wordt uitgevoerd, maar deze gaan terug verloren bij het wegschrijven van de uitvoer naar het bestand beveiligd.txt. Dit los je als volgt op:

dany@pindabook:~> echo "PindaNet" | sudo tee beveiligd.txt > /dev/null 
[sudo] wachtwoord voor root: 
dany@pindabook:~> cat beveiligd.txt 
PindaNet

De echo opdracht wordt door de gewone gebruiker uitgevoerd, terwijl de tee opdracht die de uitvoer naar het bestand beveiligd.txt wegschrijft met root rechten wordt uitgevoerd. Het doorsluizen van de uitvoer naar het /dev/null apparaat zorgt dat er niets op het scherm wordt weergegeven.

In het voorbeeld wordt het bestand door de tee opdracht overschreven, om de uitvoer aan een bestand toe te voegen, moet je de tee opdracht uitvoeren met de -a (--append) optie.

Een waarschuwing: werken met root rechten kan verregaande nare gevolgen hebben. Wees dus voorzichtig.

Redirect