Bashskript Problem?
Ich habe hier ein Bashskript, welches Dateien überwacht (noch nicht vollständig und absolut unoptimiert). Ich weiß, dass es Tools gibt, aber es ist ein Projekt für die Uni und deshalb ist Optimierung und Effizienz nicht wirklich wichtig. Ich möchte damit die Grundlagen des Shellscriptings einfach etwas lernen.
Das ist bisher das Script:
#!/bin/bash
echo "Das Skript wurde gestartet. Der Typ Ihres Betriebssystem ist "\"$OSTYPE\""."
# If-Abfrage, die das Betriebssystem erkennt und den Pfad zum überwachten Ordner oder Datei festlegt # HIER BITTE DIE PFADE ZUM ZU ÜBERWACHENDEN ORDNER EINTRAGEN
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
BASE_DIRECTORY=" " # Übergibt dem überwachten Ordner eine Variable, wenn Betriebssystem = Linux
elif [[ "$OSTYPE" == "darwin"* ]]; then
BASE_DIRECTORY="/Users/name/Library/CloudStorage/GoogleDrive-email@gmail.com/Meine Ablage/Uni/TestOrdner" # Übergibt dem überwachten Ordner eine Variable, wenn Betriebssystem = MacOs
elif [[ "$OSTYPE" == "win32" || "$OSTYPE" == "msys" || "$OSTYPE" == "cygwin" ]]; then
BASE_DIRECTORY="/g/Meine Ablage/Uni/TestOrdner" # Übergibt dem überwachten Ordner eine Variable, wenn Betriebssystem = Windows
else
echo "Das Betriebssystem ist unbekannt." # Wenn das Betriebssystem unbekannt ist, wird eine Fehlermeldung ausgegeben
exit 1
fi
DIRECTORY="$BASE_DIRECTORY" # Pfad zum Ordner
FILE="$BASE_DIRECTORY/Datei.txt" # Pfad zur Datei
FILE2="$BASE_DIRECTORY/Datei2.txt" # Pfad zur Datei2
cd "$BASE_DIRECTORY" || {
echo "Wechsel zu $BASE_DIRECTORY fehlgeschlagen!" # Wechselt in den TestOrdner oder gibt eine Fehlermeldung aus
exit 1;
}
# Funktion, um zu überprüfen, ob Dateien gelöscht wurden
checkIfDeleted() {
if [ ! -f "$FILE" ]; then
echo "Die Datei \"$(basename "$FILE")\" wurde gelöscht, umbenannt oder verschoben."
elif [ ! -f "$FILE2" ]; then
echo "Die Datei \"$(basename "$FILE2")\" wurde gelöscht, umbenannt oder verschoben."
elif [ ! -d "$DIRECTORY" ]; then
echo "Der Ordner \"$(basename "$DIRECTORY")\" wurde gelöscht, umbenannt oder verschoben."
fi
}
# Speichert den "ursprünglichen" Hash-Wert der Dateien
ORIGINAL_HASH=$(md5 -q "$FILE")
ORIGINAL_HASH2=$(md5 -q "$FILE2")
checkIfEdited() {
if [ ! -f "$FILE" ]; then # Wenn $FILE nicht existiert, dann wird das Skript hier beendet
return
fi
if [ ! -f "$FILE2" ]; then # Wenn $FILE2 nicht existiert, dann wird das Skript hier beendet
return
fi
if [ ! -d "$DIRECTORY" ]; then # Wenn $DIRECTORY nicht existiert, dann wird das Skript hier beendet
return
fi
# Berechnet den aktuellen Hash-Wert der Dateien
CURRENT_HASH=$(md5 -q "$FILE")
CURRENT_HASH2=$(md5 -q "$FILE2")
# Hash-Werte werden verglichen
if [ "$CURRENT_HASH" != "$ORIGINAL_HASH" ]; then
echo "Die Datei \"$(basename "$FILE")\" wurde bearbeitet."
# Ursprünglicher Hash-Wert wird für zukünftige Überprüfungen aktualisiert
ORIGINAL_HASH="$CURRENT_HASH"
elif [ "$CURRENT_HASH2" != "$ORIGINAL_HASH2" ]; then
echo "Die Datei \"$(basename "$FILE2")\" wurde bearbeitet."
# Ursprünglicher Hash-Wert wird für zukünftige Überprüfungen aktualisiert
ORIGINAL_HASH2="$CURRENT_HASH2"
fi
}
while true; do # Endlosschleife, die die Funktionen "checkIfDeleted" und "checkIfEdited" alle 10 Sekunden ausführt
checkIfDeleted
checkIfEdited
sleep 10
done
Ja, ich weiß, welche Probleme das Skript mit sich bringt, aber ich habe ein anderes Problem:
Wenn jemand das Skript nutzen möchte, muss er die Pfade seiner Dateien einfügen und sogar neue Variablen definieren.
Man könnte das doch so machen, dass das Skript die Liste des Ordners einliest und dann auf alle Dateien direkt zugreifen muss, ohne dass man sie in das Skript einfügen muss.
Also irgendwie mit dem Befehl "ls". Ich weiß aber nicht, wie ich das implementieren soll.
Kann mir wer helfen bitte?
3 Antworten
Jeder darf es so schmerzhaft machen wie er will.
Möglichkeiten:
BASEDIR=somedir/ #
for file in $basedir*; do
some stuff
done
Natürlich darfst Du auch über den Output von ls iterieren:
for item in `ls ...` # Neben backticks gibt es weitere Möglichkeiten
Oder Du nutzt gleich find und machst sowas wie:
find .... -exec md5 '{}' \;
und iterierst über den Output, oder Du nutzt find, iterierst über dessen Output udn rufst dann wieder md5 auf.
Du kannst dabei auch auf read zurückgreifen und solltest Dir dann auch die Bedeutung von IFS anschauen.
Zu guter letzt würde ich Dir die Advanced Bash Scripting Guide ans Herz legen, die gibt es ja nicht umsonst.
P.S.: Noch als Gedanke, Du wirst Dir vermutlich assoziative Arrays anschauen wollen, um so die Dateinamen inklusive Hashwerten aufzuheben.
FILES=($(ls -p | grep -v / | head -n 2))
# Überprüfen, ob genau zwei Dateien vorhanden sind
if [ ${#FILES[@]} -ne 2 ]; then
echo "Es sind nicht genau zwei Dateien im Ordner $BASE_DIRECTORY."
exit 1
fi
FILE="$BASE_DIRECTORY/${FILES[0]}" # Pfad zur ersten Datei
FILE2="$BASE_DIRECTORY/${FILES[1]}" # Pfad zur zweiten Datei
Problem ist, das das ganze wenn du es so mit den beiden Variablen FILE und FILE2 machst, nur bei eben genau 2 Dateien funktioniert. Ich musste es jetzt aber so machen weil du ja später immer die beiden Variablen zum vergleichen nutzt.
Nur als zusätzlichen Tipp, unter Linux könntest du dir mal inotifywait anschauen, ob es das unter Windows/Mac gibt weiss ich nicht.