Viva la Rekursion (oder was beim Aufruf rekusiver Funktionen beachtet werden muss)

Ein Get-Childitem *.ps1 -recurse listet alle Dateien mit der Erweiterung .Ps1 im aktuellen Verzeichnis und seinen Unterverzeichnissen auf. Es liegt eine sog. Rekursion vor, da sich Get-Childitem solange selber aufruft bis alle Verzeichnisse durchsucht wurden. Möchte man z.B. eine (beliebig tiefe) Verzeichnishierarchie aufbauen,  muss New-Item in einer Funktion aufgerufen werden, die sich selber aufruft. In etwa so:

function CreateDir()
{
  …
New-Item -itemtype directory -Name „TestDir“$Level
$Level++
CreateDir(„TestDir“$Level)

}

Grundsätzlich ist ein solcher Aufruf bei der PowerShell kein Problem, man muss lediglich zwei Dinge berücksichtigen: 1. Wann soll die Rekursion abbrechen? 2. Wie kann jede Rekursiosnebene ihren eigenen „Zustand“ (z.B. die Anzahl der angelegten Verzeichnisse) speichern? Beide Fragen setzen ein wenig Erfahrung und eine gewisse Ausdauer beim Finden einer funktionierenden Lösung heraus, so dass dieser Ansatz nichts für „eben mal schnell“-Lösungen ist und im Grunde auch nur von Anwendern umgesetzt werden kann, die bereits in der Programmierung/Software-Entwicklung Erfahrung gesammelt haben.

Das folgende Beispiel soll stellvertretend für die Umsetzung typischer Rekursionslösungen mit der PowerShell dienen. Ausgangssituation ist ein Skript, dass eine Verzeichnishierarchie in einem Verzeichnis mit dem Namen TestRoot angelegt, wobei die Anzahl der Verzeichnisse pro Ebene und die Anzahl der Ebenen durch Variablen vorgegeben wird. Eine direkte praktische Anwendung gibt es nicht, eher eine indirekte, die darin besteht, dass sich eine solche Verzeichnisstruktur zum Testen von rekursiven Verzeichnisoperationen eignet (etwa dem Anlegen einer Datei in jedem Verzeichnis).

Hier ist das Beispiel:

# Verzeichnisstruktur im Verzeichnis TestRoot mit variabler Tiefe anlegen
# Beispiel für eine rekursive Funktion

function Make-Dir
{
  $RootDir = $Args[0]
  $Level++
  Write-Host -fore green „Level=$Level“
  for($i=1;$i-le3;$i++)
  {
   $D = New-Item -itemtype directory -Name SubDir$i -Path $RootDir
   $Script:AnzahlDirs++
   Write-host „Angelegt: $($D.FullName)“
  }
  if ($Level -lt $MaxLevel)
  {
    Get-Childitem -path $RootDir | foreach-object {
   Make-Dir $_.FullName
  }
  }
  else { $Level=0;return}
}
$MaxLevel = 4
$AnzahlDirs=0
if (!(test-Path TestRoot)) { [void](new-item TestRoot -itemtype Directory) }
Make-Dir (join-path (get-location) TestRoot)
Write-Host -fore green „$AnzahlDirs Verzeichnisse angelegt.“

Der rekursive Aufruf ist rot hervorgehoben. Wichtig ist ferner, auf die Variable AnzahlDirs schreiben als Variable mit Script-Scope zuzugreifen, da sie ansonsten nur innerhalb der jeweiligen Rekursionsebene gültig ist. Tipp: Per rm TestRoot -force wird das gesamte Verzeichnis samt Inhalt wieder enfernt.

Das Ganze sieht einfach aus, doch daraus ein funktionierendes Beispiel zu machen hat ein wenig gedauert.

Schreibe einen Kommentar

Bitte logge dich mit einer dieser Methoden ein, um deinen Kommentar zu veröffentlichen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s