Hallo,
ich bin noch recht neu bei Linux, aber ich habe schon das Schreiben von mehr oder weniger kleinen Scripten als eine schöne kleine Beschäftigung für zwischendurch entdeckt.
Ich habe auch schon einige Sachen verfasst, aber jetzt würde ich euch erstmal gerne mein letztes Projekt zeigen und euch um eure Meinung dazu bitten.
Es geht um einen File Manager, den ich basierend auf dmenu geschrieben habe.
Möchte sich ein erfahrener Scripte-Schreiber mein Script vielleicht mal anschauen und mir als Anfänger sagen, ob das gut so ist? Ich habe mir zwar viel Mühe gegeben und und funktionieren tut es bei mir, aber ich nutze ihn noch nicht so lange und außerdem will ich sichergehen, dass es nicht nur funktioniert, sondern auch sicher funktioniert. Schließlich kann Programmieren und Scripte-Schreiben ja auch eine gefährliche Angelegenheit sein, wenn man nicht genau Bescheid weiß...
Anmerkung: Wer das Script ausprobieren möchte: Bitte nur, wenn Du es vorher genau geprüft hast! Wie gesagt, ich bin Anfänger und kann keine Garantie für die sichere Funktion des Scriptes übernehmen!
So, jetzt aber:
Erstmal eine grobe Beschreibung:
dmenu basiert ja darauf, dass es seinen Input anzeigt und die vom Nutzer getroffene Eingabe nach Output schreibt. Dabei kann der Nutzer entweder einen Menüeintrag auswählen und mit Enter bestätigen, oder etwas in die Suchzeile schreiben und mit Enter abschicken bzw. mit Shift+Enter, wenn ansonsten ein durch die Eingabe ausgewählter Menüeintrag nach Ouput geschrieben wird - s. dazu auch "man dmenu".
Mein file manger startet mit der Ansicht von "LC_ALL="C" ls -1 --group-directories-first -F" des aktuellen Arbeitsverzeichnisses, also üblicherweise $HOME. Nun kann man mit der beschriebenen Methode entweder einen Ordner aus der Liste wählen, also z.B. "Dokumente" oder man kann einen nicht in der Liste enthaltenen Ordner in die Suchleiste schreiben, wie z.B. .config/i3. In jedem Fall macht das Script "cd "Ordner"" und listet dann dessen Inhalte auf.
Durch den manuellen hinzugefügten Menüeintrag "../" kann man jederzeit auch wieder in den Parent-Ordner wechseln.
Wird eine Datei aus der Liste gewählt, wird sie mit dem für den entsprechenden mime-type eingestellen Programm geöffnet. Bei mir also z.B. plain/txt mit nano.
Wird ein grafisches Programm, also nicht nano, sondern z.B libreoffice geöffnet, beendet sich der file manager automatisch, ansonsten bleibt er im Hintergrund geöffnet und steht nach Schließen von nano (z.B.) wieder zur Verfügung.
Gibt man "+" in das Eingabefeld ein (und bestätigt ggf. mit Shift+Enter statt nur mit Enter, wenn ansonsten ein Eintrag aus der Menüliste ausgeführt wird), wechselt der file manager in die erweiterte Ansicht des aktuellen Ordners, also die Ansicht des Ordners, die sich aus "LC_ALL="C" ls -lAh --group-directories-first -F)"" ergibt.
Dort funktioniert alles genauso, wie in der einfachen Ansicht.
Mit "q" kann man die erweiterte Ansicht wieder verlassen.
Ist die Eingabe weder ein Ordner, noch eine Datei, noch "+", noch "q" (im erweiterten Modus), wird sie als Befehl ausgeführt, so z.B. "touch test" oder "rm test". Der file manager bleibt dabei immer geöffnet und aktualisiert seine Ansicht entsprechend.
Beendet wird der file manger mit ESC, dem kill-Signal von dmenu (s. man dmenu).
Hier das Script:
Code: Alles auswählen
#!/bin/bash
# License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
# This is free software; you are free to change and redistribute it.
# There is NO WARRANTY, to the extent permitted by law.
set -e
dmenu_cmd () {
dmenu -i -l 25
}
apps_path="/home/robert/.local/share/applications/"
while true; do
if [ -n "$show" ]; then echo "$show" | dmenu_cmd > /dev/null; fi
show=''
list="$(echo -e "$(pwd)\n../\n$(LC_ALL="C" ls -1 --group-directories-first -F)" | dmenu_cmd)"
if [ -d "$list" ]; then
cd "$list"
elif [ -f "$list" ]; then
type=$(file -b --mime-type "$list")
tool=$(grep -m 1 "$type" "/home/robert/.config/mimeapps.list" | sed "s@^.*=@"$apps_path"@" | cut -d ';' -f1)
if [ ! -r "$tool" ]; then exit; fi
if [ -n "$(grep 'Terminal=true' "$tool")" ]; then
urxvt -e bash -c "$(sed -n '/\[Desktop Entry\]/,/^Exec=/!d;s/Exec=//p' "$tool") "$list""
else
exec $(sed -n '/\[Desktop Entry\]/,/^Exec=/!d;s/Exec=//p' "$tool") "$list" &
exit
fi
else
if [ "$list" = '+' ]; then
while true; do
if [ -n "$show" ]; then echo "$show" | dmenu_cmd > /dev/null; fi
show=''
input="$(echo -e "$(pwd)\n../\n$(LC_ALL="C" ls -lAh --group-directories-first -F)" | dmenu_cmd)"
if [[ "$input" = "4"* ]]; then
COM=$(echo ${input#4})
if eval $COM; then
continue
else
show='An error occurred. Please press Enter.'
continue
fi
elif [[ "$input" = 'q' ]]; then
continue 2
else
list2=$(echo ${input##* })
if [ -d "$list2" ]; then
cd "$list2"
elif [ -f "$list2" ]; then
type=$(file -b --mime-type "$list2")
tool=$(grep -m 1 "$type" "/home/robert/.config/mimeapps.list" | sed "s@^.*=@"$apps_path"@" | cut -d ';' -f1)
if [ ! -r "$tool" ]; then exit; fi
if [ -n "$(grep 'Terminal=true' "$tool")" ]; then
urxvt -e bash -c "$(sed -n '/\[Desktop Entry\]/,/^Exec=/!d;s/Exec=//p' "$tool") "$list2""
else
exec $(sed -n '/\[Desktop Entry\]/,/^Exec=/!d;s/Exec=//p' "$tool") "$list2" &
exit
fi
else
show='An error occurred. Please press Enter.'
fi
fi
done
else
if eval $list; then
continue
else
show='An error occurred. Please press Enter.'
continue
fi
fi
fi
done