Bitte warten...

Bash: Ordner und Dateien

Zu den grundlegenden Vorgängen wie anlegen, umbenennen, verschieben und löschen von Ordnern und Dateien siehe den Artikel Dateisystem-Operationen. Siehe auch den Artikel Unix-Dateirechte.

Mit Bash lassen sich vielfältige Operationen an Dateien und Ordnern vornehmen. Viele dieser Operationen sind aber nicht unter allen Umständen möglich. Daher sollte man zunächst die nötigen Eigenschaften mit dem Kommando test überprüfen. Im folgenden Beispiel kommen diese Optionen zum Einsatz:

  • -e – prüft, ob ein Objekt (Datei oder Ordner) existiert
  • -d – prüft, ob ein Objekt ein Ordner ist
  • -f – prüft, ob ein Objekt eine Datei ist
  • -L – prüft, ob ein Objekt ein Symlink ist
  • -b – prüft, ob ein Objekt ein Blockgerät ist
  • -S – prüft, ob ein Objekt ein Socket ist
  • -s – prüft, ob ein Objekt ein nicht leer ist (mehr als null Bytes groß)
  • -k – prüft, ob das Sticky Bit gesetzt ist
  • -r – prüft, ob Leserechte bestehen
  • -w – prüft, ob Schreibrechte bestehen
  • -x – prüft, ob ein Objekt ausführbar ist
  • -O – prüft den Besitzer des Objekts
  • -G – prüft die Gruppe des Objekts
  • -nt – prüft, ob ein Objekt neuer als ein anderes ist
  • -ot – prüft, ob ein Objekt älter als ein anderes ist

Code kopieren
echo $HOME  # zeigt den Benutzerordner an
echo $PWD   # zeigt das Arbeitsverzeichnis an

path="${HOME}/foobar.txt"
path2="${HOME}/foobar2.txt"
if test -e "$path"; then
  echo "Objekt $path existiert.";
  echo "Dateiname:" $(basename "$path")
  echo "Ordner:" $(dirname "$path")
  if test -d "$path"; then echo "$path ist ein Ordner."; else echo "$path ist kein Ordner."; fi
  if test -f "$path"; then echo "$path ist eine Datei."; else echo "$path ist keine Datei."; fi
  if test -L "$path"; then echo "$path ist ein Symlink."; else echo "$path ist kein Symlink."; fi
  if test -b "$path"; then echo "$path ist ein Blockgerät."; else echo "$path ist kein Blockgerät."; fi
  if test -S "$path"; then echo "$path ist ein Socket."; else echo "$path ist kein Socket."; fi
  if test -s "$path"; then echo "$path ist nicht leer."; else echo "$path ist leer."; fi
  if test -k "$path"; then echo "$path hat Sticky-Bit gesetzt."; else echo "$path hat Sticky-Bit nicht gesetzt."; fi

  if test -r "$path"; then echo "Lesezugriff auf $path besteht."; else echo "Lesezugriff auf $path besteht nicht."; fi
  if test -w "$path"; then echo "Schreibzugriff auf $path besteht."; else echo "Schreibzugriff auf $path besteht nicht."; fi
  if test -x "$path"; then echo "$path ist ausführbar."; else echo "$path ist nicht ausführbar."; fi
  if test -O "$path"; then echo "Der aktuelle Benutzer ist Besitzer von $path."; else echo "Der aktuelle Benutzer ist nicht Besitzer von $path."; fi
  if test -G "$path"; then echo "Der aktuelle Benutzer ist in der Gruppe von $path."; else echo "Der aktuelle Benutzer ist nicht in der Gruppe von $path."; fi
  
  if test -e "$path2"; then
    if test "$path" -nt "$path2"; then echo "$path ist neuer als $path2."; else echo "$path ist nicht neuer als $path2."; fi
    if test "$path" -ot "$path2"; then echo "$path ist älter als $path2."; else echo "$path ist nicht älter als $path2."; fi
  fi
else
  echo "Objekt $path existiert nicht.";
fi

Möchte man den Inhalt eines Ordners rekursiv (einschließlich der Unterordner) durchsuchen, kann man das auf folgende Weise tun. Dies ist auch ein Beispiel für eine rekursive Funktion, da sie sich in Zeile 5 selbst aufruft.

Code kopieren
dirscan() {
  echo "${2}$(tput setaf 3)$(tput bold)$(basename "${1}")$(tput sgr0)"  # Ordnername
  for o in "${1}"/*; do
    if test -d "$o"; then
      dirscan "$o" "${2}  "
    else
      if [ "$(basename "$o")" != "*" ]; then echo "${2}  $(basename "$o")"; fi  # Dateiname
    fi
  done
}

dirscan "$HOME/Dokumente" ""

Objekteigenschaften auslesen

Mithilfe des Kommandos stat lässt sich eine Vielzahl von Eigenschaften eines Ordners bzw. einer Datei abfragen. Darunter so grundlegende wie die Dateigröße, der Besitzer- oder Gruppenname oder die Zugriffsrechte. Außerdem können die Zeitpunkte der letzten Statusänderung ctime, Inhaltsänderung mtime und des letzten Zugriffs atime im ISO-Format oder als Zeitstempel der Unixzeit ausgegeben werden. Für die Platzhalter %w bzw. %W wird ›Entstehungszeit der Datei‹ angegeben, was ich aber nicht bestätigen kann. Stattdessen geben diese Platzhalter mtime an. Möglicherweise bezieht sich diese Eigenschaft auf Objekte in einem Windows-Dateisystem.

Code kopieren
file=./foobar.txt
echo $(stat -c '%s' "$file")  # Dateigröße in Bytes

echo $(stat -c '%u' "$file")  # Besitzer-ID
echo $(stat -c '%U' "$file")  # Besitzer
echo $(stat -c '%g' "$file")  # Gruppen-ID
echo $(stat -c '%G' "$file")  # Gruppe
echo $(stat -c '%a' "$file")  # Rechte oktal
echo $(stat -c '%A' "$file")  # Rechte rwx

echo $(stat -c '%w' "$file")  # Entstehung ISO-Format (mtime)
echo $(stat -c '%W' "$file")  # Entstehung Unixzeit (mtime)
echo $(stat -c '%x' "$file")  # atime-ISO-Format
echo $(stat -c '%X' "$file")  # atime-Unixzeit
echo $(stat -c '%y' "$file")  # mtime-ISO-Format
echo $(stat -c '%Y' "$file")  # mtime-Unixzeit
echo $(stat -c '%z' "$file")  # ctime-ISO-Format
echo $(stat -c '%Z' "$file")  # ctime-Unixzeit

Mit dem Kommando gio info (s. auch GIO) können weitere Eigenschaften in der speziellen GIO-Hierarchie ausgelesen werden.

Code kopieren
file=./Bilder
gio=$(gio info "$file")
echo "${gio}"

gio=$(gio info "$file" | grep time::)  # filtert alle Eigenschaften des time-Zweiges
echo "${gio}"

Mit dem Kommando gio set können diese Eigenschaften auch geändert werden, sofern eine Änderung erlaubt ist. Man beachte den fehlenden Doppelpunkt nach dem Namen der Eigenschaft im Gegensatz zu der Ausgabe von gio info.

Code kopieren
# Ausgabe von gio info:
# metadata::nemo-icon-view-zoom-level: 1

gio set "$file" metadata::nemo-icon-view-zoom-level 3

Textdateien schreiben und lesen

Mit den Operatoren > und < ist es möglich, in eine Textdatei zu schreiben bzw. aus ihr zu lesen.

Code kopieren
echo "Dies ist die erste Zeile." > ./foobar.txt  # erzeugt bzw. leert die Datei und schreibt den String hinein
echo "Dies ist noch eine Zeile." >> ./foobar.txt  # fügt den String ans Ende der Datei an

contents=$(< ./foobar.txt)   # liest die gesamte Datei ein
echo "$contents"

Mit mapfile kann eine Datei Zeile für Zeile in ein Array geschrieben werden.

Code kopieren
mapfile -t < ./foobar.txt
contents=("${MAPFILE[@]}")
for ((i=0; i < ${#contents[@]}; i++)); do
  echo "${contents[i]}"
done