Nighthawk.dk

Introduktion til Bash shell

Skrevet d. 15. Aug. 2020 af Claus Nielsen.

Her beskrives grundlæggende brug af Bash shell, inklusiv "piping".

For at komme i gang skal du først have startet en Bash shell, og hvordan du gør det, afhænger af dit system:

  • Linux: Mange Linux-distributioner som Ubuntu og Mint har allerede Bash installeret fra start. Tryk på Ctrl + Alt + T eller søg efter programmet Terminal for at starte en shell.
  • Windows: Du kan bruge WSL (Windows Subsystem for Linux) til at installere f.eks. Ubuntu på Windows. Alternativt kan du bruge f.eks. Cygwin. I begge tilfælde får du kun en terminal (shell), og ikke mulighed for at tegne grafik til f.eks. plotting af data.
  • MacOS: Jeg har ikke erfaring med MacOS, men terminalen kan meget af det samme som Bash, og det skulle være muligt at køre en Bash shell på MacOS.

Grundlæggende brug af Bash

Her er først en række grundlæggende kommandoer, man bør kende:

  • cd [mappe/sti] - Gå til en anden mappe
  • ls - Vis filer/mapper i mappen
  • ls -lah - Vis mere overskuelig liste over filer/mapper i mappen
  • mkdir [navn] - Laver en ny mappe med det angivne navn
  • rm [filnavn] - Sletter filen med det angivne navn permanent
  • cp [filnavn1] [filnavn2] - Kopierer filen [filnavn1] til [filnavn2]
  • cat [filnavn] - Udskriver indholdet af filen til terminalen
  • head -n 4 [filnavn] - Udskriver de første 4 linier af filen til terminalen
  • tail -n 4 [filnavn] - Udskriver de sidste 4 liner af filen til terminalen
  • echo "Tekst" - Udskriver tekst til terminalen
  • wc -l [filnavn] - Udskriver antal linier i filen
  • exit - Lukker terminalen

Her er et eksempel på brug af terminalen:

claus@ClausDesktop:~$ mkdir bash_test
claus@ClausDesktop:~$ cd bash_test
claus@ClausDesktop:~/bash_test$ echo "Dette er en test" > testfil
claus@ClausDesktop:~/bash_test$ ls -lah
total 12K
drwxr-xr-x  2 claus claus 4.0K Aug 15 16:53 .
drwxr-xr-x 42 claus claus 4.0K Aug 15 16:52 ..
-rw-r--r--  1 claus claus   17 Aug 15 16:53 testfil
claus@ClausDesktop:~/bash_test$ cat testfil 
Dette er en test
claus@ClausDesktop:~/bash_test$ cp testfil test2
claus@ClausDesktop:~/bash_test$ ls
test2  testfil
claus@ClausDesktop:~/bash_test$ head test2
Dette er en test
claus@ClausDesktop:~/bash_test$ rm test2
claus@ClausDesktop:~/bash_test$ ls
testfil
claus@ClausDesktop:~/bash_test$ cd ..
claus@ClausDesktop:~$ rm -r bash_test

Her startede terminalen i mappen ~ som betyder "hjemme-mappen", og som svarer til /home/brugernavn (hvor "brugernavn" er mit tilfælde er "claus", dvs. /home/claus). Du kan gå ud til roden i filsystemet med cd /, og er du gået ind i en mappe kan du gå et niveau ud igen med cd ...

Vigtigt: Det er godt at vide, at de fleste programmer, der kører i terminalen, kan stoppes ved at trykke på Ctrl + C.

Nyttige programmer

Her kommer en række programmer som kan være nyttige at kende.

less [filnavn]

Viser indholdet af filen, og du kan gå op og ned i filen med piletasterne Pil Op og Pil Ned, eller Page Up og Page Down, samt Home og End for at gå til starten eller slutningen af filen. Programmet afsluttes ved at trykke på Q.

watch [kommando]

Dette program bliver ved med at udføre kommandoen periodisk indtil du afslutter med Ctrl + C. Kan f.eks. bruges til at monitorere en simulering, for at holde øje med hvor langt den er nået, ved hele tiden at se på de seneste output til en logfil:

watch -n 1 'tail -n 10 simulering.log'

I dette eksempel vises de sidste 10 linier af filen "simulering.log", og visningen bliver opdateret hvert sekund.

grep [tekst] [filnavn]

Udskriver linier fra filen, som indeholder den angivne tekst. Her er nogle eksempler:

Læg mærke til at der bruges anførselstegn hvis teksten indeholder tegn som f.eks. mellemrum ("text file" i eksemplet). Desuden er de kantede paranteser [ og ] meget nyttige: de står i stedet for ét tegn i tekststrengen, så f.eks. betyder "l[id]" at teksten skal være enten "li" eller "ld".

Bemærk at -A [antal] og -B [antal] får grep til også at udskrive et antal linier hhv. efter (After) og før (Before) de linier som indeholder søgeteksten. I eksemplet ovenfor blev der alligevel ikke skrevet flere linier ud med disse parametre da der blev fundet første og sidste linie i filen.

Du kan bruge grep -rn "noget tekst" . for at søge efter "noget tekst" i alle filer i nuværende mappe samt alle undermapper (-n giver bare linienumre).

cut -d[delimiter] -f[kolonner] [filnavn]

Kommandoen cut deler hver linie i en fil op i kolonner, adskildt af det tegn (delimiter) angiver med -d. Hvis man f.eks. vil opdele med mellemrum, kan man bruge -d' ', hvor der står et mellemrum mellem ' og '.

Med -f kan man angive numrene på de kolonner man vil have udskrevet, adskildt med komma (,), eller hvis man vil have flere kolonner efter hinanden kan man bruge en bindestreg (-). F.eks. vil -f2,4,6-9 trække kolonne 2, 4, 6, 7, 8 og 9 ud af filen.

Her er et eksempel:

claus@ClausDesktop:~/work$ cat test.txt
Hello World!
Hello again!
Adding a third line to the text file.
claus@ClausDesktop:~/work$ cut -d' ' -f2 test.txt
World!
again!
a
claus@ClausDesktop:~/work$ cut -d' ' -f2-6 test.txt
World!
again!
a third line to the
claus@ClausDesktop:~/work$ cut -d' ' -f2- test.txt
World!
again!
a third line to the text file.
claus@ClausDesktop:~/work$ cut -d'l' -f1,4 test.txt
Held!
He
Adding a third

tr -d/-s

Kommandoen tr kan fjerne eller erstatte tegn i det input, der bliver givet (input kan sendes til tr med piping, |, der bliver beskrevet længere nede i artiklen). Bruger man tr -d 'T' vil man få udskrevet filen hvor alle T'er er fjernet. Man kan f.eks. også fjerne alle mellemrum med tr -d ' ' eller alle tabulatorer med tr -d '\t'.

Ved at bruge -s i stedet for -d kan man erstatte tegn; f.eks. vil tr -s ' ' '.' fjerne alle mellemrum og indsætte et punktum hvert sted hvor mindst ét mellemrum har været. Bemærk her, at ikke alle mellemrum erstattes af punktum - hvis der er flere mellemrum lige efter hinanden, vil alle disse mellemrum erstattes af kun et enkelt punktum.

Her er et eksempel:

claus@ClausDesktop:~$ echo "Hello World!"
Hello World!
claus@ClausDesktop:~$ echo "Hello World!" | tr -d 'l'
Heo Word!
claus@ClausDesktop:~$ echo "Hello World!" | tr -s 'l' 'L'
HeLo WorLd!
claus@ClausDesktop:~$ echo "Hello World!" | tr -s 'l' '%'
He%o Wor%d!

man [kommando]

Viser hjælp (MANual/dokumentation) for hvordan en kommando virker. Prøv f.eks. man ls.

Visningen er ligesom med less, dvs. du bruger Pil Op og Pil Ned, eller Page Up og Page Down til at gå frem og tilbage, samt Home og End for at gå til starten eller slutningen. Programmet afsluttes ved at trykke på Q.

Output redirection og piping

Når du kører en kommando i Bash får du ofte bare resultatet ud som tekst i terminalen, men ofte er det rart at gemme kommandoerne output i en fil. Dette kan gøres med > eller >>, der laver output redirection, dvs. at de f.eks. kan skrive output til en fil, i stedet for at skrive det direkte i terminalen:

echo "Noget tekst..." > min_fil.txt
echo "Mere tekst til filen" >> min_fil.txt
echo "Overskriv filen!" > min_fil.txt

Hvis du bruger > vil du overskrive en eksisterende fil med outputtet fra kommandoen, mens >> bare tilføjer til en eksisterende fil (eller opretter en ny fil hvis den ikke findes).

Bemærk at der findes forskellige output streams, som programmer kan skrive til - typisk bruges stdout (standard output) eller stderr (standard error). Du kan redirecte output fra en bestemt stream ved at bruge stream id (file descriptor) foran > eller >>, hvor stdout har ID 1 og stderr ID 2:

./mit_program 1> output_fra_stdout.txt 2> output_fra_stderr.txt

Du behøver dog ikke at redirecte begge streams, og hvis du f.eks. redirecter uden noget ID vil du kun redirecte stdout (dvs. 1> er det samme som bare at bruge >). Du kan også redirecte stderr til stdout ved at bruge 2>&1, altså således:

./mit_program > output.txt 2>&1

Her vil både stdout og stderr skrives til output.txt.

Piping

Et af de vigtigste værktøjer i shellscripting er piping, hvor du redirecter output til et andet program/kommando. Dvs. input i dette andet program bliver outputtet af det første.

Til piping bruges |, og det kan gentages således at output fra et første program sendes til næste program, mens output fra næste program så sendes videre til et tredje program, osv.

Her er et eksempel:

claus@ClausDesktop:~/work$ cat test.txt
Hello World!
Hello again!
Adding a third line to the text file.
claus@ClausDesktop:~/work$ cat test.txt | grep Hello
Hello World!
Hello again!
claus@ClausDesktop:~/work$ cat test.txt | grep Hello | grep again
Hello again!
claus@ClausDesktop:~/work$ cat test.txt | grep Hello | grep again | cut -d' ' -f2
again!

Bemærk at der ikke gives noget filnavn til grep og cut her - de får i stedet input fra den kommando, som står på venstre side af pipe'en |.

Start programmer i baggrunden

Når et program startes i terminalen, er det ikke muligt at bruge terminalen igen før programmet er slut, og det er ikke altid hensigtsmæssigt. Hvis man f.eks. vil åbne en fil i teksteditoren "gedit" på Linux, er der ingen grund til, at terminalen skal blokeres så længe "gedit" kører.

Man kan derfor køre programmer i baggrunden ved at slutte en kommando af med &, som f.eks.:

gedit min_fil.txt &