0 Einleitung
             Beispiel 1: Erzeugen einer Ordnerstruktur mit leeren und zufällig gefüllten Dateien
             Beispiel 2: Erzeugung großer Textdateien
             Beispiel 3: Erstellen von (leeren) Übungsverzeichnissen
             Beispiel 4: Erstellen von Übungsdateien


0 Einleitung

Zu den Objekten im Filesystem unter Windows gehören in erster Linie Dateien, Ordner, Freigaben, Pfade und Laufwerke. Mit deren cmdlets und .Net-Klassen werden wir uns in diesem Kapitel hauptsächlich beschäftigen.

Mittels Powershellskript kann man diese Objekte erstellen, deren Inhalte auslesen und verändern, umbenennen, verschieben, löschen, filtern, Eigenschaften wie Größe und Zugriffsberechtigungen bestimmen und viele andere Dinge mehr.

Im Powershellwerkzeugkasten liegen neben den cmdlets und vielen .Net-Klassen weitere Werkzeuge wie WMI-Klassen, dem COM-Objekt "Filesystemobjekt", sowie jahrelang bewährte Tools wie robocopy oder xcopy bereit.
Kombiniert man diese Komponenten (Cmdlets, .Net/ WMI/ Com -Klassen, fertige Tools) ,  so ergibt sich im Kapitel "Filesystem" eine wiedermal riesengroße Vielfalt an Aufgaben und Beispielskripten. 
Dennoch will ich versuchen, einige aus meiner Sicht wichtige Themen anzugehen.

Ich stelle gleich zu Beginn einige Funktionen und Skripte vor, mit denen man auf einem Verzeichnis seiner Wahl Ordner und Dateien als Testumgebung erstellen kann. Die ersten beiden Beispiele sind etwas umfangreicher, die restlichen Beispiel dafür einfacher.

 

Beispiel 1: Erzeugen einer Ordnerstruktur mit zufällig gefüllten Dateien verschiedenen Alters

Set-StrictMode -Version "2.0"
Clear-Host

Function GetAlphanumericRandom{
   param($Digits=8,[String]$Flag='111', $SpaceFrequency=4,[boolean]$LineFeed=$false)
   $RandomPool=$null
   $Flag=[Convert]::ToInt32($Flag, 2)
   $MinLower=[int][char]'a' #97
   $MaxLower=[int][char]'z' #122
   $MinUpper=[int][char]'A'  #65
   $MaxUpper=[int][char]'Z'  #90
   $MinNumber=[int][char]'0' #48
   $MaxNumber=[int][char]'9' #57
   $Space =[int][char]' ' #32

   if($Flag -band 1){
     $RandomPool=[char[]]($MinLower..$MaxLower)
   }
   if($Flag -band 2){
    $RandomPool+=[char[]]($MinUpper..$MaxUpper)
   }
   if($Flag -band 4){
     $RandomPool+=[char[]]($MinNumber..$MaxNumber)
    }
   if($Flag -band 8){
     for($i=1;$i -le $SpaceFrequency;$i++){
       $RandomPool +=" "
     } #for
   }
 
   #Benutzerdefinierte zusätzliche Zeichenketten
   for($i=1;$i -le 3;$i++){
       $RandomPool +="Karl"
   }
   for($i=1;$i -le 2;$i++){
       #if($LineBreak){$RandomPool +="`n"} #Zeilenumbruch
       if($LineFeed){$RandomPool +=[Environment]::NewLine}
     }

  $ofs = ''

  [string](Get-Random -input $RandomPool -count $digits)
}#function GetAlphanumericRandom Ende

Function Create_LeereFiles_mit_nummeriertenFilenamen{
param($FileName="File",$Extension="log",$number=2)
Get-ChildItem $Path | foreach {
   for ($i=1;$i -le $number;$i++){
   [string]$j="{0:000}" -f $i
   New-Item -type "file" -path "$Path\$_" -name "file$j.$Extension" -force
   }
   }
}

Function Create_leereFiles_mit_zufaelligen_Filenamen{
  param($Extension="log",$Number=2)
  Get-ChildItem $Path | foreach {
     for ($i=1;$i -le $number;$i++){
       $FileName=GetAlphanumericRandom -digits 6 -Flag 0111 -SpaceFrequency 5
       New-Item -type "file" -path "$Path\$_" -name "$FileName.$Extension" -force
      } #for
   } #foreach
} #function

Function FilesMitInhalt_zufaelligerFilename{
  param($Extension="log",$NumberFiles=2,[int32]$NumberLines=5)
  Get-ChildItem $Path | foreach {
   for ($i=1;$i -le $NumberFiles;$i++){
     $FileName=GetAlphanumericRandom -digits 6 -Flag 0111
     New-Item -type "file" -path "$Path\$_" -name "$FileName.$Extension" -force
     Out-File -filepath "$Path\$_\$FileName.$Extension" -append -inputobject $(get-date) -width 80
     for($j=1;$j -le $NumberLines; $j++){
       $Text=GetAlphanumericRandom -digits 80 -Flag 1111 -SpaceFrequency 7 -LineFeed $true
       Out-File -filepath "$Path\$_\$FileName.$Extension" -append -inputobject $text -width 80 -encoding unicode
     } #for j
   } #for i
  } #foreach Get-ChildItem
}

Function Create_FilesMitInhalt_zufaelligerFilename_einigeTageAlt{
 param($Extension="log",$NumberFiles=2,[int32]$NumberLines=5,$AlterInTagen=31)
 Get-ChildItem $Path | foreach {
  for ($i=1;$i -le $NumberFiles;$i++){
    $FileName=GetAlphanumericRandom -digits 6 -Flag 0111
    new-item -type "file" -path "$Path\$_" -name "$FileName.$Extension" -force
    Out-File -filepath "$Path\$_\$FileName.$Extension" -append -inputobject $(Get-Date) -width 80
    for($j=1;$j -le $NumberLines; $j++){
        $Text=GetAlphanumericRandom -digits 80 -Flag 1111 -SpaceFrequency 7 -LineFeed $true
        Out-File -filepath "$Path\$_\$FileName.$Extension" -append -inputobject $Text -width 80 -encoding unicode
    } #for j
    $(get-item "$Path\$_\$FileName.$Extension").CreationTime = ([DateTime]::now).AddDays(-$AlterInTagen)
    $(get-item "$Path\$_\$FileName.$Extension").LastWriteTime = ([DateTime]::now).AddDays(-$AlterInTagen)
    $(get-item "$Path\$_\$FileName.$Extension").LastAccessTime =([DateTime]::now).AddDays(-$AlterInTagen)
   } #for i
 } #foreach
}

Function CreateFolders{
  param($FolderName="HomeUser", $Number=5)
  for ($i=1;$i -le $Number;$i++){
    [string]$j="{0:000}" -f $i
    new-item -type directory -path $Path -name "$foldername$j" -force
  }
}

#### Ab hier kann das Skript über Funktionsparameter angepasst werden ####


#  . C:\Powershell\myScripts\Config01.ps1  #DotSourcing

#unter diesem Pfad wird die Testumgebung angelegt
$Path="C:\temp\Homes" #wird -falls nicht vorhanden- automatisch angelegt

Createfolders -number 3  #number: Anzahl der Subfolder unter $Path
Create_leereFiles_mit_zufaelligen_Filenamen -number 2 -extension "nul"
Create_LeereFiles_mit_nummeriertenFilenamen -extension "ps1" -number 2
FilesMitInhalt_zufaelligerFilename -extension "log" -NumberFiles 2 -NumberLines 30
Create_FilesMitInhalt_zufaelligerFilename_einigeTageAlt -extension "txt" -NumberFiles 5 -NumberLines 3 -Alter 34
Create_FilesMitInhalt_zufaelligerFilename_einigeTageAlt -extension "txt" -NumberFiles 5 -NumberLines 3 -Alter 733

Kapitel_0 Beispiel_1.ps1.txt

Kapitel_0 Beispiel_1 mit DotSourcing.zip.txt

Anleitung:
- Das Skript legt das Verzeichnis "C:\temp\homes" an und darunter 10 Unterordner. In diese Unterordner werden einige leere und gefüllte Textdateien mit verschiedenen Dateinamen, sowie teils mit Creation- und LastWritetimes älter als 33 Tagen und 733 Tagen geschrieben. Im unteren Teil des Skripts -nach den Funktionen- kann man das gewünschte Ergebnis recht einfach anpassen.

Erklärung: 
- Die aufwändigste Funktion des Skripts ist "Function get-alphanumericRandom". Diese habe ich aus dem Kapitel Die Variablen -> 1.1.2 explizite Typzuweisung -> Beispiel 3 entnommen und dort auch erklärt. Die übrigen Funktionen sind nicht besonders spannend, daher spare ich mir deren Erklärung.

Den Block am Ende des Skripts zur Konfiguration könnte man bei häufiger unterschiedlicher Benutzung auch in eine eigene Config-Datei "Config.ps1" auslagern und mit DotSourcing einbinden. Dazu muss ein Punkt, gefolgt von einem Leerzeichen und der komplette Pfad angegeben werden


Beispiel 2: Erzeugung großer Textdateien

Set-StrictMode -Version "2.0"
Clear-Host

Function Get-AlphaNumericRandom{
   Param($Digits=8,[String]$Flag='111', $SpaceFrequency=4,[Boolean]$LineFeed=$False)
   $RandomPool=$null

   $Flag=[Convert]::ToInt32($Flag, 2)

   $MinLower=[int][char]'a' #97
   $MaxLower=[int][char]'z' #122

   $MinUpper=[int][char]'A'  #65
   $MaxUpper=[int][char]'Z'  #90

   $MinNumber=[int][char]'0' #48
   $MaxNumber=[int][char]'9' #57

   $space =[int][char]' ' #32

   if($Flag -band 1){
     $RandomPool=[char[]]($MinLower..$MaxLower)
   }
 
   if($Flag -band 2){
     $RandomPool+=[char[]]($MinUpper..$MaxUpper)
   }
 
   if($Flag -band 4){
     $RandomPool+=[char[]]($MinNumber..$MaxNumber)
     }

   if($Flag -band 8){
     for($i=1;$i -le $spaceFrequency;$i++){
       $RandomPool +=" "
     } #for
   }
     #Benutzerdefinierte zusätzliche Zeichenketten
   for($i=1;$i -le 1;$i++){
       $RandomPool +=" ErrorID:220 "
       $RandomPool +=" ErrorID:225 "
       $RandomPool +=" ErrorID:250 "
   }
   for($i=1;$i -le 2;$i++){
       #if($LineBreak){$RandomPool +="`n"} #Zeilenumbruch
       if($LineFeed){$RandomPool +=[Environment]::NewLine}
     }

  $Ofs = ''

  [String](Get-Random -input $RandomPool -count $Digits)
}#function Ende


function BigFile{
   Param($Extension="txt",$NumberFiles=1,[int32]$NumberLines=150,$FileName="Big")
       New-Item -type "File" -path "$Path" -name "$FileName.$Extension" -force
       Out-File -filepath "$Path\$FileName.$Extension" -append -inputobject $(Get-Date) -width 80
         for($j=1;$j -le $NumberLines; $j++){
            $Text=Get-AlphaNumericRandom -digits 80 -flag 1111 -SpaceFrequency 7 -Linefeed $False
            $Text=$(get-date -format g)+ "   "+$Text
             Out-File -filepath "$Path\$FileName.$Extension" -append -inputobject $Text -width 80 -encoding Unicode
       } #for j
     }
 
 $Path="C:\temp"
 
 BigFile -NumberLines 150 -Filename Big150        #ca. 25  Kb - Datei
 #BigFile -NumberLines 1500 -Filename Big1500      #ca. 255 Kb - Datei
 BigFile -NumberLines 15000 -Filename Big15000    #ca. 2,5 Mb - Datei
 #BigFile -NumberLines 150000 -Filename Big150000  #ca. 25  Mb - Datei 
#mögliche Ausgabe

   Verzeichnis: C:\temp

Mode         LastWriteTime                 Length Name  
----         -------------                 ------ ----      
-a---        26.01.2013     22:34          0 Big150.txt
-a---        26.01.2013     22:34          0 Big15000.txt

 Kap_0 Beispiel2 CreateBigTextFiles.ps1.txt

Das Ergebnis könnte also eine Datei c:\temp\Big150.txt mit 150 Zeilen folgendes Inhaltes sein. Um mit den Dateien auch eventuelle Filter untersuchen zu können, habe ich die Wörter "ErrorID: 220","ErrorID: 225" und "ErrorID: 250" zufällig eingebaut

Samstag, 26. Januar 2013 22:34:23

26.01.2013 22:34   BbdOG8ow9 fJUDET3KkQm j c  aP5htAFvNZnCVX L ErrorID:250  60y4g ErrorID:225 Mxze1H7supIRq2S ErrorID:220 rYWli
26.01.2013 22:34   rMl0y g9V1YR5zTxmAtHNiIG P QefjO7 XBE UScd ErrorID:250 Zq34DWp 62avn8 ErrorID:225  ErrorID:220 JbKwF okCLshu
26.01.2013 22:34     neP 2MfpEIkyu s3iX ErrorID:220 LmSQvHCZWF6awYx7bRlUBco184 ErrorID:225 r ErrorID:250 VJTgtGqO zh d5 0DNK9jA
26.01.2013 22:34   LOCTywm6 f3SR D50 V ErrorID:220 e ZsQYipc7aXA4Hv9FW1on2b ErrorID:250 k ErrorID:225 zBPxUhMq ljK Gdt8rJNI ugE
26.01.2013 22:34   NhztJbP ErrorID:225 T1CwjDuVL   BpxHAKY5oEdf 9vRr ErrorID:250 eFZWIGQ86sO0l7nk432Uiy aS qMc Xm ErrorID:220 g
26.01.2013 22:34   3 J BAlL65PkQcNUWne89 ErrorID:220 RVva frY m0Mijspu gK2d1 xty IoEqwXZ ErrorID:250 CzTFGODhH7 ErrorID:225 4Sb
...

Anleitung: 
Das Skript legt unter "C:\temp" Textdateien mit einer angegebenen Zahl von Zeilen an. Der Inhalt der Zeilen ist zufällig. Pfad und Anzahl der Zeilen können einfach im unteren Teil des Skripts -nach den Funktionen- angepasst werden.

Erklärung: 
Die aufwändigste Funktion des Skripts ist die Function "get-alphanumericRandom". Diese habe ich aus dem Kapitel Die Variablen -> 1.1.2 explizite Typzuweisung -> Beispiel 3 entnommen und dort auch erklärt. Die übrigen Funktionen sind nicht besonders spannend, daher spare ich mir deren Erklärung.

Oft genügen aber auch einfachere Strukturen, um Skripte ausprobieren zu können, wie in den Beispiel 3 und 4 gezeigt. 

 

Beispiel 3: Erstellen von (leeren) Übungsverzeichnissen

Set-StrictMode -Version "2.0"
Clear-Host

$Path="c:\temp\homes"
$FolderName="Home"
$Count_TestFolder=5 #soviele Ordner werden erstellt

For ($Folder=1;$Folder -le $Count_TestFolder; $Folder++){
   [String]$NameSuffix="{0:000}" -f $Folder
   New-Item -type Directory -path $Path -name $FolderName$NameSuffix
   }
#Ausgabe gekürzt

    Directory: C:\temp\homes

Mode         LastWriteTime       Length  Name       
----         -------------       ------  ----       
d----        14.09.2011 15:58            home001    
d----        14.09.2011 15:58            home002  

Beispiel 4: Erstellen von Übungsdateien

Set-StrictMode -Version "2.0"
Clear-Host

$Path="c:\temp\homes\home001"
$FileName="file"
$TextInFile="This is a text string."
$Count_TestFolder=5 #soviele Files werden erstellt

For ($File=1;$File -le $Count_TestFolder;$File++){
   [String]$NameSuffix="{0:000}" -f $File
   New-Item -type "File" -path $Path -name $FileName$NameSuffix.txt -value $TextInFile
   }
#Ausgabe gekürzt   

         Directory: C:\temp\homes\home001

Mode                LastWriteTime     Length Name
----                -------------     ------ ----     
-a---        14.09.2011     15:39         22 file001.txt
-a---        14.09.2011     15:39         22 file002.txt