staging.inyokaproject.org

Shell-Skript erstellen (Verzeichnisstruktur erstellen)

Status: Ungelöst | Ubuntu-Version: Ubuntu 14.04 (Trusty Tahr)
Antworten |

Musikarchitekt

Anmeldungsdatum:
3. Juni 2018

Beiträge: 5

Ich würde gerne ein Shell-Skript in Kali Linux erstellen, welches beim Aufruf dir.sh <name> <count> eine Verzeichnisstruktur erstellt. Name steht dabei für den Namen des zu erstellenden Hauptverzeichnisses und count für die Anzahl der zu erstellenden Unterverzeichnisse.

Im Skript soll zunächst überprüft werden, ob das angegebene Verzeichnis bereits existiert oder nicht. Falls es bereits existiert, soll es eine Abfrage für einen neuen Namen geben. Die Namen der einzelnen Unterverzeichnisse sollen generell per Abfrage festgelegt werden. Dabei soll das Hauptverzeichnis für alle Benutzer beschreibbar sein, die Unterverzeichnisse sollen jedoch nur lesbar sein. Ergänzend sollte es nach jedem Schritt noch eine Statusmeldung geben (z. B. "Verzeichnis wurde erstellt").

Meine Idee sieht bisweilen so aus:

1
2
3
4
5
6
7
8
9
V=$1
if [ -e V ]
then
  read V
  mkdir $($V)
  echo "Verzeichnis $V wurde erstellt"
else
  mkdir $($V)
  echo "Verzeichnis $V wurde erstellt"

Das wäre also erst mal mein Code für das Überprüfen bzw. Erstellen des angegebenen Hauptverzeichnisses. Abgesehen davon, dass ich mir noch nicht mal sicher bin, ob die Syntax so richtig ist (z. B. mkdir $($V), habe keine Ahnung, ob man das wirklich so schreibt), weiß ich auch nicht, wie ich die anderen Schritte angehen soll. Wie sage ich z. B., dass noch so viele Unterverzeichnisse, wie beim Skript-Aufruf angegeben, erstellt werden sollen (sicherlich irgendwas mit $2)?

Ich bin noch sehr unerfahren, was Shell-Skripte angeht, und würde mich daher riesig über Hilfe freuen.

Danke im Voraus! ☺

Marc_BlackJack_Rintsch Team-Icon

Ehemalige
Avatar von Marc_BlackJack_Rintsch

Anmeldungsdatum:
16. Juni 2006

Beiträge: 4735

@Musikarchitekt: Es gibt hier im Wiki eine Einführung in das Programmieren mit der Bash.

Ob die Syntax richtig ist kann man nachlesen und ausprobieren. Also nachlesen wie die Syntax aussieht und ausprobieren in dem Sinne, dass man das ausführen kann und feststellen wird, das man es so nicht ausführen kann, weil es syntaktisch falsch ist. ☺

$ sh test3.sh
test3.sh: 10: test3.sh: Syntax error: end of file unexpected (expecting "fi") 

Du hast Da auch schon viel zu viel Code mit viel zu vielen Fehlern, sowohl syntaktisch als auch semantisch. Das sollte nicht passieren, denn Software wird nicht erst komplett runter geschrieben und dann laufen gelassen, sondern entwickelt. Stück für Stück, und jedes Stück testet man, bevor man mit dem nächsten weiter macht. Wenn man programmieren kann, werden die Stücke die man zwischen den Testläufen schreibt grösser, aber gerade am Anfang, sollte man in kleinen Schritten vorgehen.

Beim programmieren zerlegt man das Gesamtproblem üblicherweise in Teilprobleme. Und die dann wieder in Teilprobleme. Solange bis sich so ein Teilproblem leicht mit einer Funktion in ein paar Zeilen Code lösen lässt. Diese Teillösung testet man dann. Und wenn sie funktioniert, löst man das nächste Teilproblem, solange bis man alle Teillösungen zu weiteren Teillösungen zusammengesetzt hat und damit letztendlich das Gesamtproblem gelöst ist.

Dein Problem lässt sich beispielsweise in das Anlegen eines Hauptverzeichnis und das Anlegen der festgelegten Anzahl von Unterverzeichnissen aufteilen. Wobei beide Teilprobleme ihrerseits das Teilproblem „Solange Benutzer nach Verzeichnisnamen fragen, bis das Verzeichnis angelegt werden konnte“, enthalten.

Gute Namen sind wichtig beim Programmieren, denn die sind dafür da, das der menschliche Leser versteht was ein Programm macht. Wenn Du $1 an den nichtssagenden Namen $V bindest, kannst Du das auch gleich sein lassen und $1 verwenden. Besser wäre aber so etwas wie $main_folder, dann weiss der Leser was die Bedeutung dieser Variablen ist.

Um etwas zu wiederholen gibt es Schleifen. Wenn man vor Schleifeneintritt weiss oder ermitteln kann, wie oft die Schleife durchlaufen werden soll, dann nimmt man üblicherweise eine for-Schleife.

seahawk1986

Anmeldungsdatum:
27. Oktober 2006

Beiträge: 11278

Fang doch mal mit Shell/Bash-Skripting-Guide für Anfänger an, da steht unter anderem wie man Variablen nutzt und was $() tut. (für Details gibt es das Handbuch für die Bash: https://www.gnu.org/software/bash/manual/ und den Advanced Bash-Scripting Guide). Rechte kannst du mit chown und chmod oder falls es komplexer werden soll mittels ACL setzen.

Die Test-Operatoren solltest du dir auch mal ansehen, [ -e "$PFAD" ] unterscheidet nicht, ob es eine Datei oder einen Ordner vor sich hat, [ -d "$PFAD" ] prüft, ob ein Verzeichnis mit dem Pfad existiert und [ -f "$PFAD" ] prüft, ob es eine Datei mit dem Namen gibt.

So ganz grob könnte man so ein Skript nutzen - statt fest vorzugeben, wie viele Unterverzeichnisse erstellt werden sollen, könnte man z.B. auch eine Endlosschleife nehmen, die abbricht, sobald bei der Abfrage kein Name angegeben wurde:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/bin/bash
base_dir="$1"
if  [ -d "$base_dir" ]; then
  read -p "Neuer Name für Verzeichnis: " new_basedir
  mv "$base_dir" "$new_basedir" || exit 1
  echo "$base_dir in $new_basedir umbenannt"
  base_dir="$new_basedir"
elif [ -f "$base_dir" ]; then
  echo "angegebener Pfad existiert bereits als Datei"
  exit 1
else
  mkdir -p "$base_dir" || exit 1
  echo "Verzeichnis $base_dir wurde angelegt"
fi

echo "Erstelle Unterverzeichnisse"
while :; do
    read -p "Name für neues Unterverzeichnis (leerer Name zum Beenden): " new_dir
    [ -z "$new_dir" ] && exit
    new_path="$base_dir/$new_dir"
    mkdir -p "$new_path"
    echo "Verzeichnis $new_path erstellt"
done

Die Frage, dich ich mir stelle, ist warum man für das interaktive Erstellen und Verwalten von Verzeichnissen überhaupt ein Skript will, das einen mit einer Schleife nervt, die Namen abfragt - da gibt es praktischere Tools für die interaktive Dateiverwaltung in der Shell - z.B. Midnight Commander, dired in Emacs, ranger und viele mehr.

Und wenn es keine allzu komplexe Verzeichnisstruktur werden soll, genügt ein Aufruf von mkdir gefolgt vom Setzen der Rechte für die Unterverzeichnisse:

mkdir -p basisverzeichnis/{'Unterverzeichnis 1','Unterverzeichnis 2','Unterverzeichnis 3'}
find basisverzeichnis -mindepth 1 -type d -exec chmod 755 {} + # Unterordner nur für Besitzer beschreibbar 

Musikarchitekt

(Themenstarter)

Anmeldungsdatum:
3. Juni 2018

Beiträge: 5

Danke erst mal soweit für die Antworten!

Es ist leider eine Aufgabe, die so vom Prof vorgegeben ist. 😉 Wir können daher nicht einfach andere Variablen als $0, $1 usw. verwenden. V als Variable habe ich jetzt nur genommen, um mit dem Wert von $0 (also der Verzeichnisname) in der Schleife arbeiten zu können.

Was mich jetzt z. B. interessieren würde: Wenn man in der for-Anweisung bei then mehrere Zeilen hat, müssen die irgendwie noch mit Semikolon getrennt werden? Und wenn der Ausdruck mkdir $($V) "grammatikalisch" falsch ist, wie müsste ich es dann schreiben? Es soll ja lediglich das, was sich hinter V verbirgt (also das Verzeichnis), hinter mkdir gesetzt werden.

seahawk1986

Anmeldungsdatum:
27. Oktober 2006

Beiträge: 11278

Musikarchitekt schrieb:

Was mich jetzt z. B. interessieren würde: Wenn man in der for-Anweisung bei then mehrere Zeilen hat, müssen die irgendwie noch mit Semikolon getrennt werden?

Willst du nicht der Einfachkeit halber das Handbuch lesen? Immerhin ist die Idee hinter der Aufgabe doch, dass du etwas dabei lernst:

Und wenn der Ausdruck mkdir $($V) "grammatikalisch" falsch ist, wie müsste ich es dann schreiben? Es soll ja lediglich das, was sich hinter V verbirgt (also das Verzeichnis), hinter mkdir gesetzt werden.

Siehe Zeile 12 oder 21 in meinem Beispielskript wie man auf den Wert einer Variable zugreift und ihn hinter mkdir als Argument setzt (die Bedeutung von -p als Argument von mkdir darfst du selber nachlesen).

Marc_BlackJack_Rintsch Team-Icon

Ehemalige
Avatar von Marc_BlackJack_Rintsch

Anmeldungsdatum:
16. Juni 2006

Beiträge: 4735

@Musikarchitekt: $0 ist nicht der Verzeichnisname. Und natürlich dürft ihr die Argumente an andere, sprechendere Namen binden. Andererseits bringt es nichts den Wert von $1 an einen so nichtssagenden Namen wie $V zu binden, da kann man dann auch gleich bei $1 bleiben. Das ändert nichts daran ob man das dann in einer Schleife verwenden kann oder nicht. Man bindet aber die Argumente an Namen welche dem Leser die Bedeutung der Werte klar machen, damit der Leser versteht was da im Code passiert. Wie schon gesagt sind gute Namen wichtig beim Programmieren. Das ist keine Kosmetik sondern hilft auch dem Programmierer dabei das Problem/die Lösung besser zu verstehen. Denn wenn einem zu einem Wert kein guter, passender Name einfällt, dann lässt das in der Regel den Schluss zu, das der Programmierer entweder etwas nicht verstanden hat, oder die Daten falsch strukturiert sind.

Wenn Du zu einer for-Anweisung ein then schreibst, dann sind Semikolons eher nicht das Problem, sondern das Du hier Teile von zwei verschiedenen Kontrollstrukturen vermischst. 😉

mkdir $($V) ist grammatikalisch übrigens nicht falsch. Das macht semantisch nur etwas anderes als Du vermutlich haben willst. Da das nichts exotisches enthält, kannst Du das ja mal erklären was das macht, nachdem Du Shell-Programmierung gelernt hast.

Antworten |