CLI-Adventskalender, Tag 9: Navigieren durchs Dateisystem

CLI-Adventskalender: Navigieren durchs Dateisystem

Avatar von Eric

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

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
pwd
ls
cd repos
ls
cd projekt1
ls
cd ..
cd projekt2
ls
pwd ls cd repos ls cd projekt1 ls cd .. cd projekt2 ls
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
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.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
tree -I node_modules -I .git -L 2 -d
tree -I node_modules -I .git -L 2 -d
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
cd hat ein paar nette Features.

Mit

cd ~
cd ~ kommen wir zurück ins Home-Verzeichnis, mit
cd -
cd - zurück ins Verzeichnis aus dem wir gerade gekommen sind.

Goodies von Mayflower

Keine Sorge – Hilfe ist nah! Melde Dich unverbindlich bei uns und wir schauen uns gemeinsam an, ob und wie wir Dich unterstützen können.

Ein symbolischer Link – vergleichbar mit einer Verknüpfung – baut eine schnelle Abkürzung.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
ln -s /home/eric/repos/projekt/src/classes/modules/awesome awesome
cd awesome
ln -s /home/eric/repos/projekt/src/classes/modules/awesome awesome cd awesome
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
cd schnell mal ein Alias anlegen.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
alias cdu="cd /home/eric/nervig/langer/verzeichnis/pfad"
cdu
alias cdu="cd /home/eric/nervig/langer/verzeichnis/pfad" cdu
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
find und
fzf
fzf.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
alias fcd='cd "$(find . -type d | fzf)"'
alias fcd='cd "$(find . -type d | 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.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
export AWESOME_PATH="/home/eric/repos/project/src/classes/modules/awesome"
cat $AWESOME_PATH/ManagerBuilderCompiler.java
rm $AWESOME_PATH/NotNeededAnymore.txt
export AWESOME_PATH="/home/eric/repos/project/src/classes/modules/awesome" cat $AWESOME_PATH/ManagerBuilderCompiler.java rm $AWESOME_PATH/NotNeededAnymore.txt
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
cd $AWESOME_PATH.

Soweit so Standard. Aber es gibt auch ein, zwei „magische“ Variablen.

$CDPATH
$CDPATH legt das Base-Verzeichnis für Verzeichniswechs fest.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
export CDPATH="/home/eric/repos/project/src/classes/modules"
cd awesome
export CDPATH="/home/eric/repos/project/src/classes/modules" cd awesome
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.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
export CDPATH=".:/home/eric/repos/project/src/classes/modules:/home/eric/Documents"
cd awesome
export CDPATH=".:/home/eric/repos/project/src/classes/modules:/home/eric/Documents" cd awesome
export CDPATH=".:/home/eric/repos/project/src/classes/modules:/home/eric/Documents"
cd awesome

Ist das nicht gleich viel angenehmer?

Mit

$PATH
$PATH sucht die Shell ausführbare Befehle. Es kann also geschickt sein, die eigenen Skripte dort hineinzulegen.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
export PATH=$PATH:/home/eric/skripte
backup.sh
export PATH=$PATH:/home/eric/skripte backup.sh
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
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
cp. Wenn man nicht will, dass
cp
cp die ganze Zeit stumm ist, gibt man vielleicht noch ein
-v
-v dazu und kriegt wenigstens den Namen der Datei, die aktuell kopiert wird.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
cp -rv enormes_verzeichnis backup
cp -rv enormes_verzeichnis backup
cp -rv enormes_verzeichnis backup

Aber

rsync
rsync wäre bei großen Aufgaben der bessere Kandidat. Komplett mit Fortschrittsanzeige und aktueller Geschwindigkeit.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
rsync -ahv --info=progress2 enormes_verzeichnis backup
rsync -ahv --info=progress2 enormes_verzeichnis backup
rsync -ahv --info=progress2 enormes_verzeichnis backup

Anstelle von

mv
mv kann rsync mit
--delete-source-files
--delete-source-files auch verschieben. Zum Testen kann man
-n
-n übergeben, um sich einen Überblick zu verschaffen, was nun eigentlich getan wird.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
rsync -ahvn --info=progress2 --delete-source-files enormes_verzeichnis archiv
rsync -ahvn --info=progress2 --delete-source-files enormes_verzeichnis archiv
rsync -ahvn --info=progress2 --delete-source-files enormes_verzeichnis archiv

Löschen ist auch so ein Thema. Klar, so ein

rm -rf
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:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
shred -u -v nicht-mehr-benoetigt.txt
shred -u -v nicht-mehr-benoetigt.txt
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ö…

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
find ./enormes_verzeichnis -type f | xargs -I{} shred -u -v {}
find ./enormes_verzeichnis -type f | xargs -I{} shred -u -v {}
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:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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
}
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 }
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
history mit dem Shortcut 
!42
!42, die bash_history-Datei, die Volltextsuche mit
STRG
STRG +
R
R, sowie unsere alten Freunde

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
rm -rf nerviges_verzeichnis
sudo !!
rm -rf nerviges_verzeichnis sudo !!
rm -rf nerviges_verzeichnis
sudo !!

und

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
mkdir verzeichnis
cd !$
mkdir verzeichnis cd !$
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.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
mkdir -p verzeichnis
^mkdir^cd
echo "Hello World"
^World^Mayflower
mkdir -p verzeichnis ^mkdir^cd echo "Hello World" ^World^Mayflower
mkdir -p verzeichnis
^mkdir^cd
echo "Hello World"
^World^Mayflower

… oder vielleicht will man auch nur das n-te Argument?

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
mkdir -p ganz/langer/verzeichnis/baum/hinter/parameter
cd !:2
mkdir -p ganz/langer/verzeichnis/baum/hinter/parameter cd !:2
mkdir -p ganz/langer/verzeichnis/baum/hinter/parameter
cd !:2

… oder ganz explizit das letzte Argument?

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
ps aux | sort -nrk 4 | head > processes.txt
cat !$
ps aux | sort -nrk 4 | head > processes.txt cat !$
ps aux | sort -nrk 4 | head > processes.txt
cat !$

Eine ganze Schatzkiste voller solcher Kürzel findet man in

man history
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
    STRG +
    A
    A springt zum Anfang der Zeile
  • STRG
    STRG+
    E
    E zum Ende
  • ALT
    ALT +
    F
    F geht ein Wort nach vorne
  • ALT
    ALT +
    B
    B geht ein Wort nach hinten
  • STRG
    STRG +
    L
    L macht dasselbe wie
    clear
    clear, 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
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
df -Th für eine Übersicht aller Datenträger, deren Typ, Mountpoint, Kapazität und verfügbarem Platz. Das, kombiniert mit

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
du -sh * | sort -rh
du -sh * | sort -rh
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
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.

Shell-Weisheit des Tages
Alles ist eine Datei

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:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
dd if=/dev/sda1 of=/home/eric/usbstick.img bs=4M status=progress
dd if=/dev/sda1 of=/home/eric/usbstick.img bs=4M status=progress
dd if=/dev/sda1 of=/home/eric/usbstick.img bs=4M status=progress

Diese Datei kann ich mounten wie ein Laufwerk:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
sudo mount -o loop /home/eric/usbstick.img /media/stick
sudo mount -o loop /home/eric/usbstick.img /media/stick
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.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
sudo fbi -d /dev/fb0 -T 1 -noverbose -a /home/eric/catpicture.jpg
sudo fbi -d /dev/fb0 -T 1 -noverbose -a /home/eric/catpicture.jpg
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.

Goodies von Mayflower

Keine Sorge – Hilfe ist nah! Melde Dich unverbindlich bei uns und wir schauen uns gemeinsam an, ob und wie wir Dich unterstützen können.

Avatar von Eric

Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Für das Handling unseres Newsletters nutzen wir den Dienst HubSpot. Mehr Informationen, insbesondere auch zu Deinem Widerrufsrecht, kannst Du jederzeit unserer Datenschutzerklärung entnehmen.