# Dateien und Verzeichnisse

- Zeitstempel einer Datei
- Eigenschaften von Dateien
- Globbing
- Verzeichnisse
- Dateifunktionen

## Zeitstempel einer Datei

Mit einer Datei sind i.a. Zeit- bzw. Datumsangaben verknüpft, mit deren Hilfe man beispielsweise herausfinden kann, wann der Inhalt einer Datei zum letzten Mal verändert wurde. Allerdings hängt es stark vom Filesystem (und damit vom Betriebssystem) ab, welche Zeitangaben mit einer Datei gespeichert werden und welche nicht.

Das ursprünglich unter UNIX entwickelte Perl ermöglicht den Zugriff auf die dort bekannten drei Zeitstempel:

- Zugriffszeit (atime): Hier wird festgehalten, wann zum letzten Male auf den Inhalt einer Datei zugegriffen wurde.
- Modifikationsszeit (mtime): Dieser Zeitstempel wird jedesmal aktualisiert, wenn der Inhalt einer Datei verändert wird.
- Änderungszeit (ctime): Hiermit werden Veränderungen von Dateieigenschaften (Größe, Zugriffsrechte,...) markiert.

> Zeitstempel | Dateiattribut | Funktion | veränderbar durch `utime()`?
> --- | --- | --- | ---
> atime | `-A` | `stat[8]` | ja
> mtime | `-M` | `stat[9]` | ja
> ctime | `-C` | `stat[10]` | nein

Sowohl die Dateiattributoperatoren "`-A`", "`-M`" und "`-C`" als auch die Funktion `stat()` erwarten entweder ein Filehandle oder einen Dateinamen als Argument. Allerdings unterscheiden sich die Rückgabewerte insofern, als daß erstere die Zeiten in Einheiten von Tagen in Bezug auf den Start des aufrufenden Programms (genauer: des Inhalts der speziellen Variable `$^T` bzw. `$BASETIME`) ausgeben, während `stat()` im Listenkontext in den Elementen 8 bis 10 jeweils den entsprechenden Zeitpunkt in Sekunden seit der "Epoche" (1.1.1970, 00:00 GMT) enthält.

Anwendungsbeipiel:

`#!/usr/local/bin/perl -w use strict; my $alter = (-M "test.pl"); # Gleitkommazahl! print "Letzte Änderung vor $alter Tagen\n";`

Es sei noch einmal darauf hingewiesen, daß obiges für UNIX-artige Systeme gilt - bei anderen Betriebssystemen sollte man in der jeweiligen Dokumentation nachsehen, welche Bedeutung die Rückgabewerte der genannten Operatoren bzw. `stat()` dort haben.

[Seitenanfang]

## Eigenschaften von Dateien

Neben den bereits erläuterten Zeitangaben gibt es noch eine Reihe weiterer Dateieigenschaften, die mit Hilfe von Dateiattributoperatoren abgefragt werden können. Die folgende Liste enthält nur die wichtigsten davon:

- `-r` File kann gelesen werden
- `-w` File kann beschrieben/verändert werden
- `-x` Ausführbares Programm
- `-e` Datei existiert
- `-z` Datei hat die Länge Null
- `-s` Rückgabe der Dateilänge
- `-f` File ist einfache Datei
- `-d` File ist ein Verzeichnis
- `-l` File ist ein symbolischer Link

Anwendungsbeipiel:

`#!/usr/local/bin/perl -w use strict; if(-r "test.pl") { print "lesbar\n" } else { print "nicht lesbar\n" } print "Länge ist : ".(-s "test.pl")."\n";`

Die ebenfalls schon erwähnte Funktion `stat()` liefert im Listenkontext eine Reihe von Dateieigenschaften auf einmal zurück:

> Index | Eigenschaft
> --- | ---
> 0 | Gerätenummer des Filesystems
> 1 | Inode-Nummer
> 2 | Zugriffsrechte
> 3 | Anzahl der Hardlinks
> 4 | Benutzer-ID des Dateieigentümers
> 5 | Gruppen-ID der Datei
> 6 | Geräteidentifikation
> 7 | Dateigröße (in Bytes)
> 8 | atime
> 9 | mtime
> 10 | ctime
> 11 | Bevorzugte Blockgröße für Datentransfer
> 12 | Anzahl der allozierten Blöcke

Da die Funktion `stat()` direkt die UNIX-Systemfunktion `stat()` abbildet, gilt obige Tabelle unter anderen Betriebssystemen u.U. nur mit Einschränkungen.

Beispiel:

`#!/usr/local/bin/perl -w use strict; my $datei = "test.pl"; my @a = stat($datei); print "Die Datei '$datei' ist $a[7] Bytes groß.\n";`

[Seitenanfang]

## Globbing

In einer UNIX-Shell gibt es die Möglichkeit, eine Liste von Files zu erhalten, indem man ein Muster vorgibt, das Platzhalter wie `*` oder `?` enthält. So liefert

> `ls -1 *.html`

eine einspaltige (die Option hinter "`ls`" ist die Ziffer "1") Liste aller Files, die auf `.html` enden.

Einen analogen Mechanismus gibt es in Perl durch die Funktion `glob()` sowie den sog. Rhombus-Operator "`<>`". Obiges Shell-Beispiel läßt sich dann wie folgt implementieren:

`#!/usr/local/bin/perl -w use strict; foreach my $filename (glob("*.html")) { print $filename."\n" }`

Oder auch:

`#!/usr/local/bin/perl -w use strict; foreach my $filename (<*.html>) { print $filename."\n" }`

Man kann auch die File-Liste direkt an ein Array übergeben:

`#!/usr/local/bin/perl -w use strict; my @fileliste = glob("*.html"); foreach my $filename (@fileliste) { print $filename."\n" }`

Selbst Variablen können im Dateimuster verwendet werden:

`#!/usr/local/bin/perl -w use strict; my $pfad = 'perl'; my @fileliste = <$pfad/*.html>; foreach my $filename (@fileliste) { print $filename."\n" } my $muster = '*.html'; @fileliste = <${muster}>; # Spezialfall foreach my $filename (@fileliste) { print $filename."\n" }`

Im obigen Beispiel muß im zweiten Teil `<${muster}>` anstelle von `<$muster>` stehen, da hier eine Variable alleine im Rhombus-Operator steht.

Wer es etwas genauer wissen will: in einem Ausdruck wie `<$muster>` wird `$muster` als "indirektes Filehandle" betrachtet. Damit kann man beispielsweise Filehandles als Parameter an Unterprogramme übergeben.

Beispiel:

`#!/usr/local/bin/perl -w use strict; open(FILE,'test.dat') or die "Kann Datei nicht lesen: $!\n"; print_file(\*FILE); close(FILE); sub print_file { my $handle = $_[0]; while(<$handle>) { print } }`

[Seitenanfang]

## Verzeichnisse

Ähnlich wie man Dateien zum Lesen öffnen kann, lassen sich auch Verzeichnisse behandeln, um auf die Dateinamen des Ordnerinhalts zugreifen zu können.

Beispiel:

`#!/usr/local/bin/perl -w use strict; opendir(DIR,"perl"); while(my $datei = readdir(DIR)) { print $datei."\n" } closedir(DIR);`

Mit `opendir()` wird dabei das Verzeichnis geöffnet. Das erste Argument ist hierbei das sog. "Directoryhandle", dessen Name analog zu den Filehandles aus Großbuchstaben bestehen sollte. Die Funktion `readdir()` liefert dann die einzelnen Einträge des Ordners. `closedir()` schließlich beendet den Zugriff auf das Verzeichnis.

Das aktuelle Verzeichnis kann plattformunabhängig mit Hilfe der Funktion `cwd()` des Standard-Moduls `Cwd` bestimmt werden.

Beispiel:

`#!/usr/local/bin/perl -w use strict; use Cwd; my $akt_verz = cwd(); print "aktuelles Verzeichnis : $akt_verz\n";`

Ein Verzeichniswechsel ist durch die Funktion `chdir()` möglich. Dies ist allerdings abhängig vom Betriebssystem, unter dem Perl gerade läuft, wobei insbesondere auf das Zeichen zu achten ist, das Datei-/Verzeichnisnamen im Pfad voneinander trennt.

Als Beispiel seien hier UNIX und das "klassische" MacOS gegenübergestellt:

> | UNIX | MacOS Classic
> --- | --- | ---
> Pfad-Trennzeichen | `/` | `:`
> Wechseln in höheres Verzeichnis | `chdir('..');` | `chdir('::');`
> Öffnen des aktuellen Verzeichnisses | `opendir(ABC,'.');` | `opendir(ABC,':');`

[Seitenanfang]

## Dateifunktionen

Zum Arbeiten mit Dateien gibt es folgende Funktionen; abhängig vom Betriebssystem stehen nicht immer alle zur Verfügung (z.B. gibt es keine Hard Links auf der klassischen Macintosh-Plattform):

- Änderung des Namens: `rename()`

  `#!/usr/local/bin/perl -w use strict; rename("alter_name","neuer_name");`

- Löschen einer Datei: `unlink()`

  `#!/usr/local/bin/perl -w use strict; unlink("dateiname");`

- Erzeugen eines Verzeichnisses: `mkdir()`

  `#!/usr/local/bin/perl -w use strict; my $permissions = 0777; mkdir("dirname",$permissions);`

- Löschen eines (leeren) Verzeichnisses: `rmdir()`

  `#!/usr/local/bin/perl -w use strict; rmdir("dirname");`

- Hard Link erzeugen: `link()`

  `#!/usr/local/bin/perl -w use strict; link("filename","linkname");`

- Soft Link erzeugen: `symlink()`

  `#!/usr/local/bin/perl -w use strict; symlink("filename","linkname");`

- Ändern der Zugriffsrechte: `chmod()`

  `#!/usr/local/bin/perl -w use strict; my $permissions = 0755; chmod($permissions,"prog_1","prog_2","prog_3");`

- Ändern des Besitzers: `chown()`

  `#!/usr/local/bin/perl -w use strict; my $uid = 4987; # Benutzer-ID my $gid = 33; # Gruppen-ID chown($uid,$gid,"datei");`

- Ändern der Zeitdaten: `utime()`

  `#!/usr/local/bin/perl -w use strict; my $atime = 812_000_000; # letzter Zugriff my $mtime = 822_000_000; # letzte Inhaltsänderung utime($atime,$mtime,"datei");`

  Die Zeiten sind hierbei in Sekunden seit dem 1.1.1970 anzugeben. Die aktuelle Systemzeit kann über den Operator `time` abgefragt werden:

  `#!/usr/local/bin/perl -w use strict; print "Seit dem 1.1.1970 sind "; print time; print " Sekunden vergangen.\n";`

[Seitenanfang]

Autor: Eike Grote | Version: 2.05 (24.1.2012)