echo — der einfachste Befehl mit den meisten Tricks
Grundlage
echo gibt einfach Text aus. Klingt banal, ist aber das
wichtigste Werkzeug, wenn du Skripte schreibst oder schnell etwas in eine
Datei schreiben willst.
# Einfache Ausgabe
echo "Hallo Linux-Welt"
# Mit Variablen — werden ausgewertet (Dollarzeichen)
echo "Mein User: $USER"
echo "Heute ist $(date)"
echo "Mein Home: $HOME"
# Ohne Newline am Ende — nützlich für Prompts
echo -n "Bitte eingeben: "
# Mit Escape-Sequenzen interpretieren (-e)
echo -e "Zeile 1\nZeile 2\nZeile 3"
echo -e "Tab\there\tand\tthere"
echo -e "Rot: \e[31mfehler\e[0m"
Wichtige Escape-Sequenzen mit -e
\n | Newline (Zeilenumbruch) |
\t | Tab (Tabulator) |
\\ | Backslash selbst |
\b | Backspace |
\r | Carriage Return (Zeilenanfang) |
\e[31m | ANSI: rot · \e[0m = Reset |
Single Quotes vs. Double Quotes
# Double Quotes: Variablen werden ausgewertet
echo "User: $USER"
# Ausgabe: User: admin
# Single Quotes: alles wird wörtlich genommen
echo 'User: $USER'
# Ausgabe: User: $USER
# Keine Quotes: funktioniert oft, aber riskant bei Leerzeichen
echo Hallo Welt
Im Zweifel Double Quotes. Sie schützen vor Wortgrenzen (Leerzeichen) und erlauben trotzdem Variablen. Single Quotes nur, wenn du ausdrücklich KEINE Auswertung willst (z.B. ein Beispielcode in der Doku).
Wildcards / Globbing — viele Dateien auf einmal
PflichtWildcards (auch „Globs“ genannt) sind Platzhalter, die die
Shell durch passende Dateinamen ersetzt, bevor sie den Befehl ausführt.
Damit kannst du ls *.txt sagen — und die Shell macht intern daraus
ls anna.txt bernd.txt clara.txt.
Wildcards werden von der Shell aufgelöst, nicht vom Befehl
selbst. rm sieht nie das Sternchen — es bekommt schon die
fertige Liste der Treffer übergeben. Das hat Konsequenzen: wenn nichts passt,
wird das Sternchen wörtlich übergeben, was zu komischen Fehlern führen kann.
Die vier Wildcards
| Wildcard | Bedeutung | Beispiel |
|---|---|---|
* |
beliebig viele beliebige Zeichen (auch null) | ls *.txt — alle .txt-Dateien |
? |
GENAU EIN beliebiges Zeichen | ls test?.txt — test1.txt bis testZ.txt |
[abc] |
EIN Zeichen aus der Liste | ls test[135].txt — nur 1, 3, 5 |
[a-z] / [0-9] |
EIN Zeichen aus einem Bereich | ls report-[a-c].txt |
[!abc] |
EIN Zeichen, das NICHT in der Liste ist | ls test[!0].txt — alles außer test0.txt |
Praxis-Beispiele
# Alle Dateien, die mit "m" beginnen
ls /usr/bin/m*
# Genau 3-zeichige Befehlsnamen
ls /usr/bin/???
# Alle Konfig-Dateien
ls /etc/*.conf
# Alle Bilder
ls ~/*.jpg ~/*.png ~/*.gif
# Alle Dateien, die mit a, b oder c beginnen
ls [abc]*
# Alle Zahlen-Dateien
ls test[0-9].txt
# Alle versteckten Dateien (mit Punkt am Anfang)
ls -d .*
Brace Expansion — kein Wildcard, aber verwandt
Geschweifte Klammern sind keine Wildcards im engeren Sinn — die Shell erzeugt damit Listen, OHNE auf existierende Dateien zu schauen:
# Zahlen-Range
echo {1..10}
# Ausgabe: 1 2 3 4 5 6 7 8 9 10
# Buchstaben-Range
echo {a..e}
# Ausgabe: a b c d e
# Mit Schrittweite
echo {0..20..5}
# Ausgabe: 0 5 10 15 20
# Listen
echo {anna,bernd,clara}
# Ausgabe: anna bernd clara
# Kombiniert — sehr mächtig!
mkdir -p projekt/{src,tests,docs}/{2024,2025}
# Erzeugt 6 Verzeichnisse in einer Zeile
touch backup_{jan,feb,mar}_{2024,2025}.tar.gz
# Erzeugt 6 Dateien: backup_jan_2024.tar.gz, …
# Klassiker: schnelle Kopie mit Backup
cp /etc/nginx/nginx.conf{,.bak}
# entspricht: cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak
Wildcards (*, ?, []) suchen
in existierenden Dateinamen. Brace Expansion
({ }) erzeugt Text-Listen, unabhängig davon, ob die
Dateien existieren. touch a{1..3} erzeugt drei NEUE Dateien;
ls a* listet EXISTIERENDE.
stdin, stdout, stderr — die drei Ströme
KonzeptJeder Linux-Prozess hat drei Standard-Datenkanäle (engl. „streams“). Mit Redirection lenkst du diese um — das ist die Basis von allem, was Linux mächtig macht.
| Stream | FD-Nummer | Default-Ziel | Wofür? |
|---|---|---|---|
| stdin | 0 | Tastatur | Eingabe in den Prozess |
| stdout | 1 | Bildschirm | normale Ausgabe |
| stderr | 2 | Bildschirm | Fehler-Ausgabe |
Wichtige Erkenntnis: stdout und stderr sind getrennt. Du siehst beide am Bildschirm, aber du kannst sie unabhängig umleiten.
Redirection — Ausgaben umleiten
PflichtDie wichtigsten Operatoren
| Operator | Was er macht |
|---|---|
> datei | stdout in Datei umleiten (überschreibt!) |
>> datei | stdout an Datei anhängen |
2> datei | stderr in Datei umleiten |
2>> datei | stderr an Datei anhängen |
&> datei | stdout UND stderr in dieselbe Datei |
> datei 2>&1 | klassische Variante: stdout in Datei, stderr „in stdout“ |
< datei | stdin AUS Datei lesen |
<< EOF | Here-Doc — mehrzeiliger stdin |
Live-Demo
# In eine Datei schreiben (überschreibt!)
ls -la > inhalt.txt
cat inhalt.txt
# An eine Datei ANHÄNGEN
echo "Neuer Eintrag" >> inhalt.txt
date >> inhalt.txt
cat inhalt.txt
# Nur Fehler in Datei
ls /existiert_nicht 2> fehler.log
cat fehler.log
# stdout in eine Datei, stderr in eine andere
ls /etc /existiert_nicht > gut.log 2> fehler.log
cat gut.log
cat fehler.log
# beides in eine Datei (alte Syntax)
ls /etc /existiert_nicht > alles.log 2>&1
# beides in eine Datei (kurze Syntax)
ls /etc /existiert_nicht &> alles.log
# stdin aus Datei
sort < liste.txt
# Here-Doc für mehrzeiligen Inhalt
cat > willkommen.txt << EOF
Hallo!
Willkommen bei HanovaTech.
Heute ist $(date +%F).
EOF
cat willkommen.txt
/dev/null — das schwarze Loch
/dev/null ist eine spezielle Gerätedatei, die alles
„verschluckt“ — was du dort reinschreibst, ist weg. Beim Lesen ist sie sofort
EOF. Klassische Anwendungen:
# Ausgabe komplett unterdrücken
ls -la /etc > /dev/null
# Nur Fehler unterdrücken, normale Ausgabe behalten
find / -name "*.conf" 2> /dev/null
# Alles unterdrücken (still und leise)
some-command &> /dev/null
# In Skripten, wenn du nur den Exit-Code prüfst
if grep -q "search" datei.txt &> /dev/null; then
echo "Treffer!"
fi
# Datei leeren ohne löschen
> /var/log/myapp.log
# entspricht: cat /dev/null > /var/log/myapp.log
/dev/zero — endlose Nullen
Gegenstück zu /dev/null: liefert unendlich viele Null-Bytes beim Lesen. Nützlich, um große Test-Dateien zu erzeugen:
# 10-MB-Testdatei
dd if=/dev/zero of=test.bin bs=1M count=10
# 1-GB-Datei (Vorsicht: Disk-Verbrauch!)
dd if=/dev/zero of=gross.bin bs=1M count=1024
Pipes | — Programme verketten (Vorgriff)
Vorgriff
Eine Pipe (Pipe-Symbol |, deutsche Tastatur:
AltGr+<) verbindet stdout eines Programms mit stdin des nächsten. Damit
kannst du kleine Werkzeuge zu großen Workflows verknüpfen.
# Wie viele Dateien sind in /etc?
ls /etc | wc -l
# Welche Prozesse laufen mit "ssh" im Namen?
ps -ef | grep ssh
# Top 5 RAM-Verbraucher
ps aux --sort=-%mem | head -6
# Eindeutige Shells, die User benutzen
cut -d: -f7 /etc/passwd | sort -u
# Live-Logs mit Filter
sudo tail -f /var/log/secure | grep "Failed password"
Pipes sind das Herz der Unix-Philosophie: kleine Tools, die zusammenarbeiten. Wir vertiefen das an Tag 2.
tee — Strom in zwei Richtungen schicken
tee liest stdin und schreibt es gleichzeitig auf
stdout UND in eine Datei. Der Name kommt von „T-Stück“ in der Klempnerei.
# Ausgabe sehen UND in Datei speichern
ls -la /etc | tee inhalt.txt
# An Datei anhängen statt überschreiben
date | tee -a log.txt
# Klassiker: in geschützte Datei schreiben mit sudo
echo "127.0.0.1 testhost" | sudo tee -a /etc/hosts
# Funktioniert, wo "sudo echo >>" scheitert (Redirect läuft ohne sudo)
„Im Logs-Ordner ist heute viel los — und ohne Wildcards und Umleitung bekommst du das nie schnell genug aufgeräumt. Üb das jetzt. Wer das nicht kann, ist im Admin-Alltag verloren.“
- Wechsle in
~/hanovatech/logs/(Struktur aus Lab 1.2). Falls noch nicht vorhanden: erst mitmkdir -panlegen. - Schreibe mit
echodie Zeile "Server gestartet um 08:00" in eine neue Dateistart.log. - Hänge zwei weitere Zeilen an dieselbe Datei an: "User admin eingeloggt um 08:05" und "Datum: $(date)".
- Zeige den Inhalt mit
cat.
cd ~/hanovatech/logs/ # falls nicht da: mkdir -p ~/hanovatech/logs/ && cd ~/hanovatech/logs/
echo "Server gestartet um 08:00" > start.log
echo "User admin eingeloggt um 08:05" >> start.log
echo "Datum: $(date)" >> start.log
cat start.log
- Schreibe die Liste aller Dateien in
/etc/(long format) in eine Dateietc_inhalt.log. - Versuche
cd /existiert_nicht/und leite den Fehler infehler.logum. - Schreibe in
system_info.logdrei Zeilen mit Username, Hostname und aktuellem Datum (mit dreiecho-Befehlen +>>). - Schreibe in eine Datei
alles.logsowohl stdout als auch stderr vonls /etc /existiert_nicht.
# 5)
ls -la /etc/ > etc_inhalt.log
# 6)
cd /existiert_nicht/ 2> fehler.log
# 7)
echo "User: $USER" > system_info.log
echo "Host: $(hostname)" >> system_info.log
echo "Date: $(date)" >> system_info.log
# 8) stdout + stderr in eine Datei
ls /etc /existiert_nicht &> alles.log
# alternativ: ls /etc /existiert_nicht > alles.log 2>&1
- Erzeuge mit einem einzigen
touchdie Dateientest1.txtbistest10.txt. Tipp: Brace Expansion. - Liste alle Dateien auf, die mit
testbeginnen. - Liste nur die Dateien, die mit
testbeginnen und genau eine Ziffer haben (also test1.txt bis test9.txt, nicht test10). - Liste nur
test1.txt,test3.txt,test5.txt. - Erzeuge zusätzlich:
report_anna.txt,report_bernd.txt,daten_2024.csv,daten_2025.csv. - Liste alle
report_-Dateien auf. - Liste alle
.csv-Dateien auf.
# 9)
touch test{1..10}.txt
# 10)
ls test*
# 11) nur einstellige Zahlen → ? deckt genau 1 Zeichen ab
ls test?.txt
# matched test1.txt bis test9.txt — test10.txt fällt raus, weil "10" zwei Zeichen sind
# 12) nur 1, 3, 5
ls test[135].txt
# 13)
touch report_anna.txt report_bernd.txt daten_2024.csv daten_2025.csv
# 14)
ls report_*
# 15)
ls *.csv
- Lösche alle
test*.txt-Dateien mit einem Befehl. - Lösche alle
.csv-Dateien mit einem Befehl. - Lösche alle
report_-Dateien. - Lass dir mit
ls -lbestätigen: nur die *.log-Dateien (start.log, etc_inhalt.log, fehler.log, system_info.log, alles.log) sind übrig.
# 16)
rm test*.txt
# 17)
rm *.csv
# 18)
rm report_*
# 19)
ls -l
# erwartet: nur die *.log-Dateien
- Zähle mit
wc -lwieviel Zeilenetc_inhalt.loginsgesamt hat (Pipe!). - Schreibe in einer einzigen Zeile sowohl auf den Bildschirm als auch in eine
Datei
system.log: "Test um $(date)". Tipp:tee. - Erstelle mit Brace Expansion 10 Backup-Dateien:
backup_2024-01.tar.gzbisbackup_2024-10.tar.gz.
# 20)
cat etc_inhalt.log | wc -l
# oder einfacher: wc -l etc_inhalt.log
# 21)
echo "Test um $(date)" | tee system.log
# 22)
touch backup_2024-{01..10}.tar.gz
Wenn ja: das war das letzte Lab von Tag 1. Du beherrschst jetzt das Erzeugen, Verwalten und schnelle Filtern von Dateien. Zeit für das Tages-Quiz und das Cheat-Sheet!
Kontrollfragen zum Kapitel
Selbst-Check- Was unterscheidet
echo "$USER"vonecho '$USER'? - Was bedeuten die drei Wildcards
*,?,[abc]? - Wer löst Wildcards auf — die Shell oder der aufgerufene Befehl?
- Was unterscheidet Wildcards von Brace Expansion
{1..10}? - Welche Nummern haben stdin, stdout und stderr?
- Was ist der Unterschied zwischen
>und>>? - Wie leitest du nur Fehler in eine Datei um?
- Wie leitest du stdout UND stderr in dieselbe Datei? Nenne zwei Schreibweisen.
- Wozu ist
/dev/nullda? - Wofür nutzt man
tee?
- Double Quotes werten Variablen aus (
$USER → admin). Single Quotes geben den Text wörtlich ($USER → $USER). *= beliebig viele Zeichen,?= genau ein Zeichen,[abc]= ein Zeichen aus der Liste.- Die Shell löst Wildcards auf, BEVOR der Befehl aufgerufen wird. Der Befehl sieht nur die fertige Liste.
- Wildcards matchen existierende Dateien. Brace Expansion erzeugt Text-Listen unabhängig von der Existenz.
- stdin = 0, stdout = 1, stderr = 2.
>überschreibt die Zieldatei.>>hängt an.befehl 2> fehler.logbefehl &> datei(kurz) oderbefehl > datei 2>&1(klassisch)./dev/nullist eine „Mülltonne“ — alles, was reingeht, ist weg. Praktisch um unerwünschte Ausgabe oder Fehler verschwinden zu lassen.teeschreibt stdin gleichzeitig auf stdout UND in eine Datei. Klassisch fürs Loggen + Anzeigen, und um in geschützte Dateien zu schreiben (echo X | sudo tee -a /etc/...).