Powershell: Spaß mit Arrays

18. November 2015

Beim Finden von Dateien mit Get-ChildItem im Verzeichnis hatte ich viel Spaß. Solange mehre Dateien vorhanden waren, hat alles wunderbar funktioniert, sobald aber nur eine Einzelne vorlag nicht. Warum?

In folgendem Code suche ich alle txt-Dateien unterhalb meines Ordners .Data. Für jede Datei soll eine Zeile ausgegeben werden. Eigentlich einfach, aber das Powershell Script funktioniert nicht immer:

$items = Get-ChildItem -Path .Data -Filter *.txt
for($i = 0; $i -le $items.Length 1; $i++){
     Write-Host("Item $($i) :$($items[$i])") }

 

Bei zwei gefunden Dateien sieht der Output so aus:

Item 0 :File1.txt
Item 1 :File2.txt
 

Liegt nur eine Datei vor, kommt es nicht zum Aufruf von Write-Host. Warum? Geben wir mal $items.Count, $items.Length und $items.GetType().FullName aus:

Count   :2
Length  :2
Type    :System.Object[]
 

Nun anstatt mit zwei mit nur einer Datei:

Count   :1
Length  :0
Type    :System.IO.FileInfo
 

Wait, What? Length ist 0, weil das untypisierte Ergebnis Get-ChildItem mal ein Array und mal ein FileInfo ist. Wie immer gibt es mehre Lösungen:

  • Immer per Count zugreifen
  • Immer durch @() ein Array erzwingen
  • Sonderfall im Code
  • ….

Die 1. Lösung ist selbsterklärend, aber hier mal die 2.:

$items = @(Get-ChildItem -Path .Data -Filter *.txt)
for($i = 0; $i -le $items.Length 1; $i++){
     Write-Host("Item $($i) :$($items[$i])") }

 

Nun erhält man auch bei einer Datei:

Count   :1
Length  :1
Type    :System.Object[]
 

Vieles ist schnell und einfach in untypisierten Skriptsprachen machbar. Ohne Compiler aber erst zur Laufzeit prüfbar und damit nicht so einfach zu finden und zu testen.