Fischer-Bayern.de
Letztes Update: 12.01.2005 | 1:11:31 Uhr
Rekursive Handler 
Peter Fischer

In AppleScript kann auch rekursiv programmiert werden. Rekursive Programmierung bedeutet, daß ein Handler sich selbst aufruft. Damit das Skript nicht in einer Endlosschleife landet, muß genau bestimmt werden, ab wann oder unter welchen Bedingungen der Handler aufhören soll, sich selbst aufzurufen.

Die häufigste Anwendung eines rekursiven Handlers besteht wohl darin, Dateien eines Ordners und dessen Unterordner abzuarbeiten.

Das folgende Beispiel-Skript stammt von Bill Briggs. Es schiebt alle Dateien in den Papierkorb.

Sie werden sich wohl fragen, für was das jetzt gut sein soll. Nun, Sie haben sich mit Sicherheit ein bestimmtes Ordnungs-System geschaffen. Ihre Dateien legen Sie immer in bestimmte Ordner.

Nach einem Backup benötigen Sie die Dateien nicht mehr auf Ihrer Festplatte. Jetzt haben Sie 3 Möglichkeiten.

  1. Sie löschen die Dateien per Hand aus den jeweiligen Ordnern
  2. Sie löschen die gesamten Ordner samt Inhalt und legen danach die Ordnerstruktur neu an
  3. Sie benutzen das folgende Skript


Der "on run"-Handler wird eigentlich nicht gebraucht. Er zeigt jedoch beim Doppelklicken des Skripts eine kleine Kurzanleitung.

on run
   display dialog ¬
      "So wird das nichts!¬
   Ziehen Sie einen Ordner auf das Skript.¬ 
   Alle Dateien, die sich im Ordner befinden,¬
   werden dann in den Papierkorb gelegt." buttons {"OK"} ¬
      default button 1 with icon caution
end run

Nützlicher ist allerdings dieser "on run"-Handler:

on run
   set derOrdner to choose folder
   MachWas(derOrdner)
end run

Durch die Verwendung von "choose folder" wird dem Skript die Referenz eines Ordners übergeben.

Bei Verwendung des "on open"-Handlers wird dem Skript nicht die Referenz zu dem Objekt, das man daraufzieht übergeben, sondern eine Liste mit Referenzen. In unserem Fall ist es zwar nur 1 Referenz (die des Top-Level-Ordners), sie muß jedoch zuerst aus der Liste extrahiert werden.
on open derOrdner
   set aktuellerOrdner to (item 1 of derOrdner)
   MachWas(aktuellerOrdner)
   -- Kurzfassung: MachWas(item 1 of derOrdner) 
end open

on MachWas(BearbeitungsOrdner)
   tell application "Finder"
      delete every file of BearbeitungsOrdner
      set OrdnerInhalt to ¬
         (every item of BearbeitungsOrdner)
      repeat with einObjekt in OrdnerInhalt
         my MachWas(einObjekt)
      end repeat
   end tell
end MachWas

Zunächst werden also alle Dateien der obersten Ordnerebene gelöscht. Danach werden die verbleibenden Objekte (das können jetzt nur weitere Ordner sein) in einer Variablen gespeichert. Diese Ordner-Liste wird dann in der repeat-Schleife abgearbeitet, wobei der Handler wiederum aufgerufen wird. Befinden sich also weitere Ordner in einem Ordner, werden diese alle abgearbeitet.


Das Beispiel-Skript zeigt zwar das Prinzip der Rekursion auf, ist aber nicht ganz optimal. Es werden zunächst alle Dateien bearbeitet (in den Papierkorb verschoben) und das was übrig bleibt müssen dann wohl zwangsläufig Ordner sein, die dann nacheinander in der selben Weise abgearbeitet werden.

Dadurch, dass nicht wirklich geprüft wird, ob es sich bei einem Objekt um einen Ordner handelt, ist das Skript nicht universell einsetzbar.

Deshalb hier noch ein anderes Skript.

-- Run-Handler zum debuggen
on run
   set theFileList to (choose folder) as list
   repeat with theFile in theFileList
      File_or_Folder(theFile)
   end repeat
end run


on open theFileList -- Per Drag & Drop wird -- eine Liste mit Referenzen an das Skript übergeben repeat with theFile in theFileList File_or_Folder(theFile) end repeat end open

-- Prüfung, ob es sich um einen Ordner oder -- eine Datei handelt on File_or_Folder(theFile) set theInfo to info for theFile if folder of theInfo then -- nicht in einen Finder-Tell-Block setzen! tell application "Finder" -- Inhaltsliste des Unterordners erstellen -- benötigt Finder-Tell-Block für 'every item' set FolderList to every item of theFile end tell repeat with theFolder in FolderList set theFolder to theFolder as alias -- wichtig für OS X (* Ohne 'as alias' enthält die Variable 'theFolder' nur den Namen des Ordners als Unicode Text. *) -- rekursiver Aufruf des Handlers my File_or_Folder(theFolder) end repeat else -- Kein Ordner, also Datei bearbeiten ProcessIt(theFile) end if end File_or_Folder

-- Dateien werden bearbeitet on ProcessIt(theFile) tell application "Finder" if locked of theFile = false then set locked of theFile to true else set locked of theFile to false end if end tell end ProcessIt

Ich hoffe, Sie können das hier Gezeigte in Ihren Skripts gebrauchen.

Peter Fischer




 

 

Workshop



snow@fischer-bayern.de

Ebene 1