PowerShell Powershell Dateien Kopieren/Vergleichen

HappyLittleTree

Cadet 1st Year
Registriert
Mai 2004
Beiträge
11
Hallo, ich möchte in 8 Ordnern, die jeweils in demselben Verzeichnis liegen PDF- und XML-Dateien miteinander vergleichen. Wenn die Namen der Dateien in dem Ordner übereinstimmen, sollen diese in ein Zielverzeichnis kopiert und anschließend von dem kopierten Ordner gelöscht werden. Wenn das Verzeichnis leer ist, soll nichts passieren.

Mein Problem ist, dass sich die Dateien in den Ordern momentan auch untereinander vergleichen. Ich möchte aber nur in einem Ordner die Dateien miteinander vergleichen, nicht in allen. Sind die Dateien in einem Ordner alle miteinander verglichen worden, soll das gleiche bei den restlichen Ordnern geschehen. Wenn es zu einer Datei keine Übereinstimmung im Namen, zischen PDF und XML Datei gibt, oder sonstige Fehler auftreten soll eine E-Mail verschickt und ein Logeintrag erstellt werden. In diesem Schritt darf die einzelne Datei dann nicht kopiert werden. Leider werden Dateien zu denen es keine Übereinstimmung gibt, aber trotzdem mit kopiert.

Hier mein bisheriger Code:

PowerShell:
$Verzeichnis = @(Get-ChildItem D:\power\ -directory).FullName

$PDF = (Get-Childitem $Verzeichnis –File -Include *.pdf -Recurse)

$XML = (Get-Childitem $Verzeichnis –File -Include *.xml -Recurse)

$Value = $True #E-Mail schicken

$counter = 0

$Pfad = ""

$PfadXML = ""

$PfadPDF = ""

do{

for($i=0; $i -lt $PDF.length; $i++){

for($a=0; $a –lt $XML.length; $a++){


if($XML[$a] -eq $PDF[$i] -AND (get-childitem $Verzeichnis[$counter]).count -ne 0){               #if($XML[$a].BaseName -contains $PDF[$i].BaseName){

Write-Host $XML[$a] "gleich" $PDF[$i]

$PfadPDF = $Verzeichnis[$counter]+"\"+$PDF[$i]

$PfadXML = $Verzeichnis[$counter]+"\"+$XML[$a]

#$hell = Get-Item -Path $Verzeichnis[$counter]+"\"+$XML[$i]

Move-Item -path "$PfadXML" -Destination "D:/power/z1/"  -verbose

Move-Item -path "$PfadPDF" -Destination "D:/power/z1/"  -verbose

    }elseif((get-childitem $Verzeichnis[$counter]).count -eq 0){

    write-host $Verzeichnis[$counter] "Verzeichnis leer"

    break

    }else{

    Write-host $XML[$a] "nicht gleich" $PDF[$i]}

}
}

$counter++

}while($counter -le 8)}
 
Kannst du die einzelnen Schritte in ein Ablaufdiagramm darstellen bitte?
 
Wenn ich das richtig sehe sollte es reichen wenn du das -Recurse beim einlesen der PDF und XML Dateiliste rausnimmst.

Wieso er die Datei kopiert ist mir allerdings ein Rätsel. Das kann ja nur passieren wenn er nie in das else reingeht. Da musst du deinen Vergleich mal neu prüfen.
 
ablauf.JPG
 
Zuerstmal: PowerShell ist nicht Batch. :)

Will sagen: geh das Ganze lieber objektorientiert an und mit den Möglichkeiten, die PowerShell hat. Leg Funktionsgruppen an, die einzelne Prozesse abbilden - zB gemäß des Diagramms über mir. Das macht die Sache nicht nur übersichtlicher, sondern auch schneller.

Dazu am Besten von ganz oben anfangen. Was soll passieren? Das steht ja im Diagramm. Was muß innerhalb der Kästels des Diagramms passieren? Evtl weiter aufschlüsseln und das dann modellieren.

Beispiel (nur konzeptionell, nicht getestet):
Code:
$Path = [System.IO.DirectoryInfo]::new("D:\Power") # Referenz aufs Stammverzeichnis. Kann man ggf auch  in den PARAM()-Block stecken


$Path.GetDirectories() |# Alle Verzeichnisse (direkt) darunter...
% {
    $thisDir = $_ # Rückreferenz aufs aktuelle Verzeichnis
    $thisDir.GetFiles('*.xml) | #Alle XML-Dateien in diesen Verzeichnissen...
    %{
$matchedSet = "" | Select File, Matched # Ergebniszuordnung (Datei, hat PDF)
$matchedSet.File = $_ # ... das Dateiobjekt landet als Eigenschaft File ...
$matchedSet.Matched =  [System.IO.FileInfo]::new(('{0}\{1}.pdf" -f $thisDir.FullName, $_.BaseName)).Exists # ... wähle die, für die es (im selben Verzeichnis) PDF-Dateien mit dem gleichen Namen gibt ...
 $matchedSet # und gib die Zuordnung für jede dieser Dateien aus
     } 
}
Hinten sollte jetzt eine Liste von Zuordnungen herauskommen (zumindest war das der Plan ^^), wo drin steht, für welche Datei (in .File) es eine zugehörige PDF-Datei gibt (in .Matched).

Das Ganze schmückst Du ein bissel aus als Funktion, zB function Get-MatchedFiles, evtl noch Parameter (zB -Path <Stamm>) drumherum und nun rufst Du das einmal auf und hast die Liste mit den Dateien, die interessieren.

Den Rest machst Du mit den restlichen Teilen ebenfalls. Das Ganze kommt in eine .psm1-Datei und fertig ist das Modul, welches Du mit Import-Module <Pfad zur PSM1-Datei> importieren kannst, wodurch nun alle festgelegten Funktionsnamen (hier also Get-MatchedFiles, Send-Mail und Copy-MatchedPair, cf. weiter unten) zur Verfügung stehen.

Dann kommt in die PS1-Datei nur noch eine Abbildung des Diagramms in PowerShell-Syntax und beschränkt sich auf sowas wie
Code:
Get-MatchedFiles -Path D:\Power |  # von oben
% {
if( $_.Matched )  # Alle die mit dem Match, ie wo es PDF *und* XML gab...
{
Copy-MatchedPair $_ -Destination <wohin> # note: $_.File geht natürlich genauso, man muß halt schauen, was für einen sinnvoller erscheint; da hier .Matched immer True ist, darf argumentiert werden, daß $_.File völig ausreicht, weil .Matched keine Information liefert
}
else
{
Send-Mail # mit entsprechenden Parametern, falls die nicht in Send-Mail bereits definiert wurden
}
   }

Es ist nicht wichtig, was die einzelnen Prozesse genau tun. Wichtig ist nur, DAß sie es tun. Deswegen können die in den Hintergrund. Hier können sie wiederverwendet werden, ohne daß man groß nachdenken muß.

Aber die Struktur, ie. wie die Prozesse zusammenarbeiten sollen, DAS ist interessant und von Fall zu verschieden. Daher kann das nicht in den Hintergrund (das Modul), sondern muß in den Vordergrund (die Scriptdatei), wo man dann reingucken kann und sofort sieht, was da überhaupt passiert.
 
Zurück
Oben