Heute beschäftigen wir uns mit der Navigations durchs Dateisystem. Denn … es ist die ultimative Newbiehürde. Wenn wir mit der Kommandozeile anfangen, lernen wir banale Formen von elementaren Befehlen und kombinieren sie in endloser, anstrengender Monotonie.
Navigieren durchs Dateisystem
pwd ls cd repos ls cd projekt1 ls cd .. cd projekt2 ls
Sehr früh scheint der Fall klar zu sein: Für einfache Befehle ist die Kommandozeile vielleicht super, aber um uns auf unserer Festplatte zurechtzufinden, brauchen wir einen graphischen Dateimanager.
Oder?
Pflanzt einen Baum und dann betrachtet ihn
tree
generiert eine wunderschöne Darstellung des kompletten Verzeichnisbaumes mit dem aktuellen Verzeichnis als Wurzel. Wenn das zu viel Output liefert, geht man vielleicht nur eine Ebene tiefer und beschränkt sich auf Verzeichnisse. Und vielleicht lässt man notorisch große Verzeichnisse aus.
tree -I node_modules -I .git -L 2 -d
Plötzlich hat man einen Röntgenblick und eine feingranularere Darstellung als mit dem klassischen Baum im File Explorer.
Warum zu Fuß gehen, wenn man beamen kann?
cd
hat ein paar nette Features.
Mit cd ~
kommen wir zurück ins Home-Verzeichnis, mit cd -
zurück ins Verzeichnis aus dem wir gerade gekommen sind.
Ein symbolischer Link – vergleichbar mit einer Verknüpfung – baut eine schnelle Abkürzung.
ln -s /home/eric/repos/projekt/src/classes/modules/awesome awesome cd awesome
Und wie für alles andere, kann man auch für cd
schnell mal ein Alias anlegen.
alias cdu="cd /home/eric/nervig/langer/verzeichnis/pfad" cdu
Das Alias möchte man nach anfänglichem Testen vielleicht auch in seiner .bashrc verankern.
Wer faul sein möchte ohne sich auszukennen, dem helfen unsere alten Freunde find
und fzf
.
alias fcd='cd "$(find . -type d | fzf)"'
Warum überhaupt sich von der Stelle bewegen?
Wem ein Alias zu spezifisch ist, der kann sich die wichtigen Pfade auch in Variablen legen.
export AWESOME_PATH="/home/eric/repos/project/src/classes/modules/awesome" cat $AWESOME_PATH/ManagerBuilderCompiler.java rm $AWESOME_PATH/NotNeededAnymore.txt
… oder natürlich auch cd $AWESOME_PATH
.
Soweit so Standard. Aber es gibt auch ein, zwei „magische“ Variablen. $CDPATH
legt das Base-Verzeichnis für Verzeichniswechs fest.
export CDPATH="/home/eric/repos/project/src/classes/modules" cd awesome
Dort lassen sich auch mehrere Verzeichnisse definieren. Man möchte vielleicht, dass die Shell zuerst im aktuellen Verzeichnis schaut. Könnte sonst nervig werden.
export CDPATH=".:/home/eric/repos/project/src/classes/modules:/home/eric/Documents" cd awesome
Ist das nicht gleich viel angenehmer?
Mit $PATH
sucht die Shell ausführbare Befehle. Es kann also geschickt sein, die eigenen Skripte dort hineinzulegen.
export PATH=$PATH:/home/eric/skripte backup.sh
Und immer dran denken: Murks mit Umgebungsvariablen wird erst permanent, wenn es in der .bashrc landet! Ein schnelles exit
rettet hier schon einmall die Situation und die gescheiterten Versuche kann man zur Reparatur aus der History fischen. Womit wir schon beim nächsten Thema wären.
Jetzt aber auch was tun!
Die häufigsten Operationen sind es zu kopieren, verschieben, löschen und Archive zu entpacken.
Zum Kopieren von – sagen wir mal – einem Verzeichnis mit vielen Dateien und einiger Größe denkt man zuerst an cp
. Wenn man nicht will, dass cp
die ganze Zeit stumm ist, gibt man vielleicht noch ein -v
dazu und kriegt wenigstens den Namen der Datei, die aktuell kopiert wird.
cp -rv enormes_verzeichnis backup
Aber rsync
wäre bei großen Aufgaben der bessere Kandidat. Komplett mit Fortschrittsanzeige und aktueller Geschwindigkeit.
rsync -ahv --info=progress2 enormes_verzeichnis backup
Anstelle von mv
kann rsync mit --delete-source-files
auch verschieben. Zum Testen kann man -n
übergeben, um sich einen Überblick zu verschaffen, was nun eigentlich getan wird.
rsync -ahvn --info=progress2 --delete-source-files enormes_verzeichnis archiv
Löschen ist auch so ein Thema. Klar, so ein rm -rf
ist schnell, effektiv und sauber, aber leider nicht so gründlich, wie es sein könnte. Wer sicher gehen will, dass eine Datei auch forensisch nicht mehr herstellbar ist, dem hilft:
shred -u -v nicht-mehr-benoetigt.txt
Leider unterstützt shred keine Verzeichnisse. Das ist ein komplett unüberwindbares Hindernis, dem wir nicht mit einer Unix-Pipe gerecht werden kö…
find ./enormes_verzeichnis -type f | xargs -I{} shred -u -v {}
Fehlen noch Archive. Es gibt so viele davon und meistens will ich mich nicht mit den Eigenheiten diverser Packprogramme beschäftigen. Ich will sie einfach nur in einen neuen Ordner auspacken, um zu vermeiden, dass sie mir meinen Download-Ordner zuspammen. Wenn ihr ähnlich faul seid, schreibt euch einfach eine Funktion in eure .bashrc, die in etwa so aussieht:
auspacken() { if [ ! -f "$1" ]; then echo "Datei nicht gefunden." return 1 fi local archiv="$1" local ordner="${archiv%.*}" mkdir -p "$ordner" case "$archiv" in *.tar.bz2) tar -xjf "$archiv" -C "$ordner" ;; *.tar.gz) tar -xzf "$archiv" -C "$ordner" ;; *.tar.xz) tar -xf "$archiv" -C "$ordner" ;; *.lzma) tar --lzma -xf "$archiv" -C "$ordner" ;; *.bz2) bzip2 -dk "$archiv" && mv "${archiv%.*}" "$ordner" ;; *.rar) unrar x "$archiv" "$ordner/" ;; *.gz) gzip -dk "$archiv" && mv "${archiv%.*}" "$ordner" ;; *.tar) tar -xf "$archiv" -C "$ordner" ;; *.tbz2) tar -xjf "$archiv" -C "$ordner" ;; *.tgz) tar -xzf "$archiv" -C "$ordner" ;; *.zip) unzip "$archiv" -d "$ordner" ;; *.Z) uncompress "$archiv" ;; *.7z) 7z x "$archiv" -o"$ordner" ;; *.xz) unxz "$archiv" && mv "${archiv%.*}" "$ordner" ;; *.exe) cabextract "$archiv" -d "$ordner" ;; *) echo "Das Format kenne ich noch nicht. ^^" ; return 1 ;; esac }
Ich sage es noch einmal
Wir erinnern uns an alte Bekannte aus dem Artikel zu bash. Wir haben Pfeiltaste nach oben für die letzten Befehle ,die wir so eingetippt haben, history
mit dem Shortcut !42
, die bash_history-Datei, die Volltextsuche mit STRG
+ R
, sowie unsere alten Freunde
rm -rf nerviges_verzeichnis sudo !!
und
mkdir verzeichnis cd !$
um Befehle bzw. Parameter noch einmal zu nutzen. Hier gibt es noch mehr.
Man kann zum Beispiel schnell einen String im letzten Befehl ersetzen.
mkdir -p verzeichnis ^mkdir^cd echo "Hello World" ^World^Mayflower
… oder vielleicht will man auch nur das n-te Argument?
mkdir -p ganz/langer/verzeichnis/baum/hinter/parameter cd !:2
… oder ganz explizit das letzte Argument?
ps aux | sort -nrk 4 | head > processes.txt cat !$
Eine ganze Schatzkiste voller solcher Kürzel findet man in man history
.
Hüpf, hüpf, hüpf
Schon mal einen langen Befehl in bash eingegeben und ewig herumgescrollt? Bash unterstützt EMACS-Shortcuts (zsh hat einen vim-modus, vielleicht ist es Zeit für mich zu wechseln …).
STRG
+A
springt zum Anfang der ZeileSTRG
+E
zum EndeALT
+F
geht ein Wort nach vorneALT
+B
geht ein Wort nach hintenSTRG
+L
macht dasselbe wieclear
, lässt aber den Inhalt der aktuellen Zeile stehen
Es ist sogar möglich, Marks zu setzen und Makros aufzunehmen. Für Leute, die es wirklich übertreiben wollen.
man readline
ist euer Freund.
Hab ich noch Platz?
Wie viel Platz hab ich noch auf meiner Partition oder meinem Stick? Was frisst gerade den ganzen Speicher? Hier helfen df -Th
für eine Übersicht aller Datenträger, deren Typ, Mountpoint, Kapazität und verfügbarem Platz. Das, kombiniert mit
du -sh * | sort -rh
… liefert eine sortierte Übersicht des Speicherplatzverbrauchs aller Dateien und Verzeichnisse im aktuellen Verzeichnis.
Natürlich kann auch unser alter Freund find mit find . -type f -size +300M
die Suche erheblich abkürzen.
Ich habe gemerkt, dass ich nach und nach grafische Dateimanager immer weniger benutzt habe. Vielleicht macht ihr ja eine ähnliche Erfahrung.
Ich habe keine Quelle dafür gefunden. Es ist eine von diesen mündlichen Traditionen, die von EntwicklerIn zu EntwicklerIn weitergegeben wurden.
„In Unix, everything is a file.“
Es ist ein zentraler Designgrundsatz, der sich auch in modernen Unix-Systemen wiederfindet. Alles ist eine Datei. Jedes Gerät, das von meinem Betriebssystem erkannt wird, hat eine korrespondierende Datei. Mein Bildschirm, meine Festplatte, meine Tastatur, alle lassen sich mit Text füttern und/oder spucken Text aus.
Wenn ich ein Images meines USB-Sticks erstellen möchte geht das so:
dd if=/dev/sda1 of=/home/eric/usbstick.img bs=4M status=progress
Diese Datei kann ich mounten wie ein Laufwerk:
sudo mount -o loop /home/eric/usbstick.img /media/stick
Mit Werkzeugen wie fbi kann ich jpegs direkt in meinen Framebuffer schreiben und anzeigen, ganz ohne X-Server und ganz ohne andere Programme.
sudo fbi -d /dev/fb0 -T 1 -noverbose -a /home/eric/catpicture.jpg
Warum ist das wichtig? Weil alle Programme die wir in den letzten Tagen betrachtet haben mit Dateien interagieren. Von der niedrigsten Hardware zum abstraktesten Container, alles kann mit den Tools gesteuert werden, die wir jetzt schon kennengelernt haben. Das, mehr als alles andere, ist der Grund, warum die Shell so mächtig ist.
Schreibe einen Kommentar