Jump to content

Skript für Ordnerstruktur teilweise kopieren


Direkt zur Lösung Gelöst von BOfH_666,
Der letzte Beitrag zu diesem Thema ist mehr als 180 Tage alt. Bitte erstelle einen neuen Beitrag zu Deiner Anfrage!

Empfohlene Beiträge

Was hast Du denn schon bisher? Zeig doch mal bitte Dein Script? Ohne auf den gleichen Monitor zu schauen und die gleiche Systemumgebung zu sehen, ist es manchmal schwer, sich etwas so vorzustellen, dass man es mit einem Script beackern möchte. ;-)  Ich kann mir Deine Ordner-Struktur und wie Du was sichern möchtest bisher nicht so richtig vorstellen. Vielleicht erzeugst Du einfach mal eine kleinere aber immernoch representative Besispiel-Ordner-Struktur und machst uns davon einen Screenshot oder eine textuelle Ausgabe und erklärst daran, was Du nun genau machen möchtest.

Link zu diesem Kommentar

Hi,

 

ja klar kein Thema.

 

So sieht die Ordnerstruktur aus die als Quelle dient:

Quelle.png

 

 

Die kopierten Daten sollen dann so aussehen:

Ziel.png

 

 

Übergeordnet gibt dann immer noch die Ordner Projekte mit den Jahreszahlen. Hier ein Screenshot der Quelle. Diese Ordner, also ein Projektordner pro Jahr soll auch am Ziel so vorhanden sein. In diesen Ordnern sind dann eben X Ordner mit den Projekten vorhanden

Projektordner.png

 

So sieht es dann z.B. im Ordner Projekte_2020 aus:

Projekte-Beispiel.png

bearbeitet von noobi
Link zu diesem Kommentar

:D Ich habe das nicht überlesen, ich habe nur nichts was ich konkret vorzeigen kann.

 

Ich habe ein paar Snipsel, aber komme einfach nicht weiter. Mit dem Test-Path kann ich ja prüfen ob Ordner mit dem Präfix B??_ bestehen, bekomme dann ein True zurück. Doch hier werden doch dann alle Ordner geprüft. Ich müsste doch dann aber direkt pro Ordner prüfen und direkt kopieren. Auch die Prüfung ob die Ordner PDF Dateien enthalten funktioniert ja, wobei ich die wie gesagt auch weglassen könnte.

 

#Quelle auf Server
$QuellPfad = "C:\Quelle\Desktop\Kopier-Skript\Test\Quelle"

#Ziel auf dem NAS
$ZielPfad = "C:\Ziel\Desktop\Kopier-Skript\Test\Ziel"

#Praefix nachdem gesucht werden soll
$Parameter = "B??_"

#Testen ob der Ordner vorhanden ist
Test-Path -Path 'C:\Quelle\Desktop\Kopier-Skript\Test\Quelle\Projekte_*\*\B??_*\*'

#Ermitteln ob Ordner Zeichnungen Dateien enthält
if((get-childitem $QuellPfad).count -eq 0){ echo "Keine Zeichnungen gefunden..." }else{ echo "Es sind Zeichnungen vorhanden!" }

# Die kompletten Pfade der gesuchten Ordner ausgeben
#$Paths = Get-ChildItem -Directory $QuellPfad -Recurse | where {$_.Name -match $Parameter} | % {$_.FullName}

# Die gefundenene Ordner per Robocopy ins ZielVerzeichnis kopieren, dabei den kompletten pfad rekonstruien (ohne den laufwerksbuchstaben, da sonst ein ":" im Namen ist)
#$Paths | % {robocopy $_ (split-path $_ -NoQualifier).ForEach({"$ZielPfad$_"}) /E}

#Daten Kopieren
Copy-Item -Path $Quellpfad -Destination $Zielpfad -Force -Filter

 

Link zu diesem Kommentar
vor einer Stunde schrieb noobi:

:D Ich habe das nicht überlesen, ich habe nur nichts was ich konkret vorzeigen kann.

Aber das ist doch was, was Du vorzeigen kannst ... es ging nicht darum, dass Du etwas perfekt Funktionierendes zeigen sollst ... dann bräuchtest Du ja auch nicht hier fragen ...  ;-)

 

OK, so lange ich nebenbei Zeit habe, können wir uns langsam rantasten ...

Immer unter der Voraussetzung, dass ich das alles richtig verstanden habe, kannst Du mit folgendem Snippet die Ordner ermitteln. die mit einem "B" und zwei darauffolgenden Ziffern beginnen und in denen PDF-Dateien liegen. Bitte prüfen und zurückmelden. :achtung:;-) 

$QuellPfad = 'C:\Quelle\Desktop\Kopier-Skript\Test\Quelle'
$ZielPfad = 'C:\Ziel\Desktop\Kopier-Skript\Test\Ziel'
$SuchMuster = '\\B\d{2}_'

$PotenzielleBackupOrdner = Get-ChildItem -Path $QuellPfad -Directory -Recurse | 
    Where-Object {$_.FullName -match $SuchMuster} |
        ForEach-Object {
            $DateiSuchMuster = Join-Path -Path $_.FullName -ChildPath '*.pdf'
            if (Test-Path -Path $DateiSuchMuster) {
                $_
            }
        }
$PotenzielleBackupOrdner.FullName

 

bearbeitet von BOfH_666
Link zu diesem Kommentar
"C:\Desktop\Kopier-Skript\Test\Quelle\Projekte_2019\190042_Name Ort Projektname\B01_Aufmass\*.pdf" wird analysiert - Unbekannte Escape-Zeichenfolge \U.
In C:\Desktop\Kopier-Skript\Test_V2.ps1:6 Zeichen:19
+     Where-Object {$_.FullName -match $SuchMuster} |
+                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : OperationStopped: (:) [], ArgumentException
    + FullyQualifiedErrorId : System.ArgumentException

Die Variable $_ scheint das Problem zu sein. Zeichen 19 = $. Muss die Variable $_ in PowerShell auch erst definiert werden wie in .NET? Oder ist das ein anderes Problem?

Habe jetzt mal die Variable zuvor erstellt, ändert aber auch nichts am Fehler...

 

Zitat

$_ = ''

 

 

Link zu diesem Kommentar

$_ ist die sogenannte Pipeline-Variable. Sie representiert das gerade in der Pipeline befindliche Object - wird also automatisch befüllt und sollte auf überhaupt gar keinen Fall direkt deklariert oder sonst irgendwie für eigene Zwecke missbraucht werden. ;-)

Ich hab den Code gerade nochmal bei mir getestet - er läuft und liefert (wenigstens mit meinen Beispiel-Ordnern) das erwartete Ergebnis. Hast Du den Code so benutzt, wie ich ihn gepostet hatte, oder hast Du ihn "angepasst"? Der in der Fehlermeldung angezeigte Pfad dürfte an dieser Stelle so nicht auftauchen.

 

Edit: Oooops ... Kommando zurück!! ich hatte einen Fehler eingebaut. ich hab den Code korrigiert - versuch jetzt nochmal, bitte

bearbeitet von BOfH_666
Link zu diesem Kommentar

Hi,

 

jetzt läuft es ohne Fehler durch. Das ganze muss ich jetzt mit dem Copy-Item Befehl verknüpfen, wo ich schon vor dem nächsten Problem stehe.

 

Nur zum Verständnis: Dein Skript durchsucht jetzt mit der Where Schleife alle Ordner nach dem B??_ Präfix ab und prüft. Dieses Ergebnis wird dann nochmals gefiltert nach Ordnern die nicht leer sind. Sämtliche Ordner werden dann in die Variable $Potentielle BackupOrdner geschrieben, die ich dann zum kopieren weiterverwenden kann. Habe ich das soweit richtig verstanden?

 

Kopieren von Quelle zu Ziel ist klar, die Selektierung erfolgt dann über Filter über die Variable $PotentielleBackupOrdner, sodass alle Ordner die diesem Filter entsprechen kopiert werden?! Dann bekomme ich aber leider nur den Ordner "Quelle" im Ziel erstellt...

 

#Daten Kopieren
Copy-Item -Path $QuellPfad -Destination $Zielpfad -Force -Filter $PotenzielleBackupOrdner.FullName

Ich sehe dich schon in meinen Gedanken, wie du du die Hände über dem Kopf zusammenschlägst und die Augen rollst :aetsch2:

Link zu diesem Kommentar

 

 

vor 1 Stunde schrieb noobi:

jetzt läuft es ohne Fehler durch. Das ganze muss ich jetzt mit dem Copy-Item Befehl verknüpfen, wo ich schon vor dem nächsten Problem stehe.

Da ist schon Deine Einstellung falsch. Das ist kein Problem, sondern eine Herausforderung. 

vor 1 Stunde schrieb noobi:

Nur zum Verständnis: Dein Skript durchsucht jetzt mit der Where Schleife alle Ordner nach dem B??_ Präfix ab und prüft. Dieses Ergebnis wird dann nochmals gefiltert nach Ordnern die nicht leer sind. Sämtliche Ordner werden dann in die Variable $Potentielle BackupOrdner geschrieben, die ich dann zum kopieren weiterverwenden kann. Habe ich das soweit richtig verstanden?

Fast. Get-ChildItem liefert mit den angegebenen Parametern ALLE Ordner, aus denen dann mittels Where-Obejct die Ordner herausgefiltert werden, in deren Pfad das Suchmuster auftaucht. Bis hierhin noch keine Schleife ... nur Pipeline. Jetzt kommt die Schleife mit Foreach-Object. Darin wird erstmal das Datei-Suchmuster aus dem kompletten Pfad des aktuellen Ordners und des Datei-Musters zusammengebaut. Das wird dann mit Test-Path benutzt, um zu prüfen, ob der aktuelle Ordner PDF-Dateien enthält. Wenn ja, wird das aktuell in der Pipeline befindliche Objekt ausgegeben und damit in der Variablen $PotentielleBackupOrdner gesammelt.

vor 1 Stunde schrieb noobi:

Kopieren von Quelle zu Ziel ist klar, die Selektierung erfolgt dann über Filter über die Variable $PotentielleBackupOrdner, sodass alle Ordner die diesem Filter entsprechen kopiert werden?! Dann bekomme ich aber leider nur den Ordner "Quelle" im Ziel erstellt...

Der nächste Teil ist ein bissl knifflig. Ich gehe mal davon aus, dass Du nicht wirklich den ganzen Pfad im Ziel wiederhergestellt haben willst, sondern nur den Teil der nach Deinem $QuellPfad kommt.  Wir müssen also den kompletten Pfad um den "Anfangs-Pfad" kürzen.

$PotenzielleBackupOrdner = Get-ChildItem -Path $QuellPfad -Directory -Recurse | 
    Where-Object {$_.FullName -match $SuchMuster} |
        ForEach-Object {
            $DateiSuchMuster = Join-Path -Path $_.FullName -ChildPath '*.pdf'
            if (Test-Path -Path $DateiSuchMuster) {
                [PSCustomObject]@{
                    FullName = $_.FullName
                    ShortName = $_.FullName -replace [REGEX]::Escape($QuellPfad)
                }
            }
        }  
$PotenzielleBackupOrdner

Wir benutzen den -replace Operator um den Teil des Pfades zu entfernen, der dem $QuellPfad entspricht. -replace arbeitet mit regulären Ausdrücken. Deshalb müssen wir alle Zeichen, die in regex als "spezielle" Zeichen gelten "escapen".

 

So ...  kannst ja schon mal probieren, den Ziel-Pfad zusammen zu bauen ... ich komm nachher wieder ... 

 

 

 

 

Link zu diesem Kommentar

Vielen Dank für deine Hilfe an der Stelle schonmal...

 

...Ich mach mich dann mal an den Ziel-Pfad... :victory:

Ist doch im Prinzip genau das Gleiche, nur das noch der Laufwerksbuchstabe am Shortname angehängt bzw. davor gesetzt werden muss.

#ZielPfad erstellen
$PotenzielleBackupZielOrdner = Get-ChildItem -Path $QuellPfad -Directory -Recurse | 
    Where-Object {$_.FullName -match $SuchMuster} |
        ForEach-Object {
            $DateiSuchMuster = Join-Path -Path $_.FullName -ChildPath '*.pdf'
            if (Test-Path -Path $DateiSuchMuster) {
                [PSCustomObject]@{
                    FullName = $_.FullName
                    ShortName = 'M:' + $_.FullName -replace [REGEX]::Escape($QuellPfad)
                }
            }
        }  
$PotenzielleBackupZielOrdner

 

Die Ausgabe ergibt folgendes:

$PotenzielleBackupOrdner

\Projekte_2019\190042_Name Ort Projektname\B03_Zeichungen

 

$PotenzielleBackupZielOrdner

M:\Projekte_2019\190042_Name Ort Projektname\B03_Zeichungen

 

Der ShortName ist ja mein gewünschter Zielpfad, das kopieren mit dem ShortName bringt aber die gleiche Fehlermeldung wie zuvor...

Copy-Item -Path $PotenzielleBackupZielOrdner.ShortName -Destination $PotenzielleBackupZielOrdner -Force 

 

bearbeitet von noobi
Link zu diesem Kommentar

Kann den der ShortName, der den korrekten Zielpfad beinhaltet nicht für den Copy-Item Befehl genutzt werden? Komme hier nicht weiter.

PS C:\WINDOWS\system32> G:\Kopier-Skript\Test_V8.ps1

FullName                                                    ShortName                                                  
--------                                                    ---------                                                  
F:\Projekte_2019\190042_Name Ort Projektname\B03_Zeichungen Z:\Projekte_2019\190042_Name Ort Projektname\B03_Zeichungen
Z:\Projekte_2019\190042_Name Ort Projektname\B03_Zeichungen
Copy-Item : Das Laufwerk wurde nicht gefunden. Ein Laufwerk mit dem Namen "@{FullName=F" ist nicht vorhanden.
In G:\Kopier-Skript\Test_V8.ps1:38 Zeichen:1
+ Copy-Item -Path $Test -Destination $PotenzielleBackupZielOrdner -Forc ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (@{FullName=F:String) [Copy-Item], DriveNotFoundException
    + FullyQualifiedErrorId : DriveNotFound,Microsoft.PowerShell.Commands.CopyItemCommand

 

bearbeitet von noobi
Link zu diesem Kommentar
  • Beste Lösung
vor 8 Stunden schrieb noobi:

...Ich mach mich dann mal an den Ziel-Pfad... :victory:

Ist doch im Prinzip genau das Gleiche, nur das noch der Laufwerksbuchstabe am Shortname angehängt bzw. davor gesetzt werden muss.

Nee ... wir werden doch jetzt nicht anfangen, Pfade oder Laufwerksbuchstaben im Code hart zu verdrahten ...   ich hätte vielleicht dazusagen sollen: "Pfoten weg von meinem Code! "  ;-)  ... nicht meinen Code anpassen - eigenen ergänzen.  ;-) :D 

Dieser Teil hier:

$QuellPfad = 'C:\Quelle\Desktop\Kopier-Skript\Test\Quelle'
$ZielPfad = 'C:\Ziel\Desktop\Kopier-Skript\Test\Ziel'
$OrdnerSuchMuster = '\\B\d{2}_'

$PotenzielleBackupOrdnerListe = Get-ChildItem -Path $QuellPfad -Directory -Recurse | 
Where-Object { $_.FullName -match $OrdnerSuchMuster } |
ForEach-Object {
    $DateiSuchMuster = Join-Path -Path $_.FullName -ChildPath '*.pdf'
    if (Test-Path -Path $DateiSuchMuster) {
        [PSCustomObject]@{
            FullName  = $_.FullName
            ShortName = $_.FullName -replace [REGEX]::Escape($QuellPfad)
        }
    }
}

... war doch nur dazu da, zu zeigen, wie man die zu kopierenden Ordner ermittelt und die Pfade entsprechend aufbereitet. Die damit erzeugte Liste $PotenzielleBackupOrdnerListe können wir dazu benutzen, den Zielpfad zusammenzubauen und den Copy-Job anzustoßen:

foreach ($PotenzielleBackupOrdner in $PotenzielleBackupOrdnerListe) {
    $KopierZielPfad = Join-Path -Path $ZielPfad -ChildPath $PotenzielleBackupOrdner.ShortName
    "Quelle : '$($PotenzielleBackupOrdner.FullName)' - Ziel: '$($KopierZielPfad)'"
    # Robocopy.exe $PotenzielleBackupOrdner.FullName $KopierZielPfad *.pdf 
}

Die robocopy-Zeile ist noch auskommentiert. Wenn Du geprüft hast, ob die ausgegebenen Pfade zu Deinen Anforderungen passen, kannst Du das "#" vor robocopy entfernen.  ... trotzdem nochmal mit Test-Daten und Test-Pfaden testen bitte!! 

Wenn dann mit den Test-Daten alles wie gewünscht funktioniert, brauchst Du nur noch die Variablenzuweisungen vom Anfang des Codes anpassen und es passt auch für die produktiven Daten.

 

vor 6 Stunden schrieb noobi:

Kann den der ShortName, der den korrekten Zielpfad beinhaltet nicht für den Copy-Item Befehl genutzt werden? Komme hier nicht weiter.


Copy-Item : Das Laufwerk wurde nicht gefunden. Ein Laufwerk mit dem Namen "@{FullName=F" ist nicht vorhanden.
In G:\Kopier-Skript\Test_V8.ps1:38 Zeichen:1
+ Copy-Item -Path $Test -Destination $PotenzielleBackupZielOrdner -Forc ...

 

Doch, aber dann musst Du diesen auch angeben. Wie Martin schon erwähnte, ist $PotenzielleBackupOrdnerListe ein Array von Objekten mit Eigenschaften. Es gäbe zwar Möglichkeiten, das so zu bauen, dass sich Copy-Item die richtige Eigenschaft aus dem Object rauspickt, aber wir wollen ja sowieso robocopy benutzen. Und das kann damit eben nicht umgehen. Also müssen wir die entsprechende Eigenschaft der Objekte explizit angeben.

 

Du hattest erwähnt, dass Du Dich näher mit dem Thema Scripting befassen möchtest. Das ist mit Sicherheit eine sehr gute Idee. Du solltest Dir ein bissl Zeit nehmen, um Dir die Grundlagen von Powershell draufzuschaffen. 

Ein guter Einstieg, wie ich finde, ist immernoch der Video-Kurs mit Jeffrey Snover: Getting Started with Powershell. Und wenn Du was zum Nachschlagen brauchst, kannst Du Dir das hier anschauen: Windows PowerShell™ 4: TFM.  ... beides kostenlos. :thumb1:

bearbeitet von BOfH_666
Link zu diesem Kommentar
Der letzte Beitrag zu diesem Thema ist mehr als 180 Tage alt. Bitte erstelle einen neuen Beitrag zu Deiner Anfrage!

Schreibe einen Kommentar

Du kannst jetzt antworten und Dich später registrieren. Falls Du bereits ein Mitglied bist, logge Dich jetzt ein.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung jetzt entfernen

  Only 75 emoji are allowed.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor-Fenster leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

×
×
  • Neu erstellen...