pit-80
Goto Top

Dateien nach und nach verschieben

Hallo zusammen,

ich hoffe, es kann mir jemand helfen.
Ich finde einfach die Lösung nicht.

Ich muss aus einem Quellordner knapp 6000 Dateien nach und nach, max. 50 Dateien alle 10 Minuten, in ein Zielordner verschieben.
In dem Zielordner werden die Dateien abgeholt und verarbeitet.

Meine Idee wäre es den Task Scheduler zu nutzen und alle 10 Minuten ein PowerShell Script oder eine Batchdatei zu starten, die dann jeweils 50 Dateien vom Quell- zum Zielordner verschiebt.

Hat jemand eine Idee wie das Script oder die Batchdatei aussehen könnte?

Content-ID: 82440337378

Url: https://administrator.de/contentid/82440337378

Ausgedruckt am: 21.11.2024 um 12:11 Uhr

Kraemer
Kraemer 23.07.2024 um 16:37:17 Uhr
Goto Top
Moin,

das wird mit allergrößter Wahrscheinlichkeit nicht so funktionieren, wie du dir das vorstellst.
Da muss man sich ein bischen mehr Mühe geben und das Ganze in ein Skript packen, welches dafür sorgt, das es zu keinem Fehler kommt.

Andersherum ist das Ganze auch per Hand in gerade einmal 2,5 Tagen erledigt.

Gruß
erikro
erikro 23.07.2024 um 16:47:43 Uhr
Goto Top
Moin,

das wäre schnell hingeschrieben mein Ansatz. Keine Garantie und nicht getestet:

$quellordner = x:\quelle
$zielordner = x:\ziel

do {

    $files = Get-ChildItem -path $quellordner-file | select -First 50
    foreach($file in $files) {

        try {
            move-item -Path $file.fullname -Destination $zielordner\$file.name
        }
        catch {
            #Fehlerbehandlung, wenn das schief geht
        }

    }
    Start-Sleep -Seconds 600

} while($(get-childitem -Path $quellordner -file))

hth

Erik
it-frosch
Lösung it-frosch 23.07.2024 um 17:21:51 Uhr
Goto Top
Hallo Pit-80,

das ist gar nicht so schwer.
Du gehst in einer Schleife über alle Dateien und fügst nach dem kopieren einer Datei zu Sicherheit 13 sek Pause ein,
bevor die nächste Datei kopiert wird.
Das wäre wahrscheinlich der einfachste Weg.

10 min = 600 sek 600/50 = 12 sek um das Limit von 50 nicht zu überschreiten.
Deshalb habe ich 13 sek vorgeschlagen.

$QUELLE = "C:\TMP\"  
$ZIEL = "C:\TMP_ZIEL\"  
$Abstand_in_sek = 13
$count = 0
$Dateien = Get-ChildItem -Path $QUELLE | %{$_.Name}
foreach ($datei in $Dateien) {

# eine Datei kopieren
Copy-Item -Path "$($QUELLE)$datei" -Destination "$($ZIEL)"  
$datei
# Pause einbauen
Start-Sleep -Seconds $Abstand_in_sek

# Zeit anzeigen
Get-Date

# Zähler hochzählen
$count=$count+1

}

Write-host "$($count) Dateien kopiert"  

Das Ergebnis sieht dann so aus:
datei1

Dienstag, 23. Juli 2024 17:19:45
datei2
Dienstag, 23. Juli 2024 17:19:58
datei3
Dienstag, 23. Juli 2024 17:20:11
datei4
Dienstag, 23. Juli 2024 17:20:24
4 Dateien kopiert

Das ist jetzt nicht schön oder elegant, sollte aber funktionieren.

Grüße vom it-frosch
it-frosch
it-frosch 23.07.2024 aktualisiert um 17:23:24 Uhr
Goto Top
@eriko
genau, das ist wesentlich eleganter als mein Entwurf auch wen meiner getestet ist. face-smile

Grüße vom it-frosch
Pit-80
Pit-80 23.07.2024 um 17:50:30 Uhr
Goto Top
Hey,
vielen Dank für eure Antworten, das wird sicher weiterhelfen.

@it-frosch:
Das mit den 13 Sekunden ist eine prima Idee und wird sicher so funktionieren.

Ich werde es morgen direkt mal testen.

Viele Grüße
Pit-80
rubberman
rubberman 23.07.2024 um 18:15:35 Uhr
Goto Top
Hallo,

wir haben so was Ähnliches am Laufen, nur nicht als Script. ERP System erzeugt Textdatei für einen Auftrag, Anderes System verschiebt und liest diese für eine halbautomatische Fertigungssteuerung. Aber das nur am Rande.
Worauf ich hinaus will ist eine Erfahrung die wir gemacht haben:
Hin und wieder wurde die Datei bereits gefunden, da sie vom ERP angelegt war, hatte aber noch keinen Inhalt. Heißt es wurde eine Null-Byte-Datei verschoben. Das ERP hat sie brav wieder angelegt und geschrieben. Der erneute Versuch sie zu verschieben ist dann aber auf Fehler gelaufen, da sie im Ziel schon existierte. Genauso gut könnte das aber auch mitten im Schreiben der Datei passieren, wenn sie in dem Moment nicht gelockt sein sollte. Typischer Fall von Race Condition zwischen zwei konkurrierend laufenden Prozessen.

Quick and dirty Lösung: In so einer Polling Schleife ist sowieso irgendeine Form von Sleep eingebaut. Wo, ist grundsätzlich erst mal egal. Im Script von @erikro haben wir das am Ende der do-while Schleife, könnte man aber ebenso zwischen der Definition der $files Variable und der foreach Schleife einbauen. Das eliminiert zwar nicht die Race Condition, aber die Wahrscheinlichkeit dass es jemals crasht tendiert gegen Null.
Ablauf wäre also
  • Dateinamen die zu finden sind in ein Cache.
  • Warten bis die Wahrscheinlichkeit hoch genug ist dass sie fertig geschrieben sind.
  • Nur die Dateien verschieben die im Cache sind (keine eventuell bereits neu hinzugekommenen).

Steffen
MirkoKR
MirkoKR 23.07.2024 um 19:19:39 Uhr
Goto Top
Hi.

... knapp 6000 Dateien zu
... max 50 Dateien
... innerhalb 10 Minuten

Offen ist,
...ob das eine einmalige Aktion ist, oder
...ob kontinuierlich - und
...wie viele in welchem Zeitraum

hinzukommen.

Außerdem ist die Position bon Quell- und Zielordner - derselbe Rechner pder Netzwerk - ggf. interessant ...

... weil: in einem lange zurückliegenden ähnlichem Projekt habe ich den "Quellordner" als Verknüpfung zum Zielordner angelegt, wodurch die Dateien direkt dort abgelegt wurden ...

Ansonsten bedarf es so oder so ja schon benannter Prüfung, ob die Datei final geschrieben ist ...
Pit-80
Pit-80 23.07.2024 um 20:13:21 Uhr
Goto Top
Hi,

vielen Dank für die weiteren Hinweise.

Das ist eine einmalige Aktion.
Es sind Dateien die nochmal verarbeitet werden müssen, da i.O..-Dateien aufgrund eines Kommunikationsfehlers zur Datenbank, in den Error-Ordner gelandet sind.
Jetzt sollen alle "Fehler"-Dateien, die in dem Zeitraum geschrieben wurden, nochmals verarbeitet werden.

Wahrscheinlich werden wir die Dateien eher nachts oder am Wochenende einspielen. Da ansonsten der normale Betrieb (ca. 15000 Dateien am Tag) gestört werden könnte.

Ich werde das morgen ersteinmal auf dem Testsystem prüfen.

Schönen Abend und viele Grüße
Pit-80
MirkoKR
MirkoKR 23.07.2024 aktualisiert um 20:21:30 Uhr
Goto Top
... bleibt die Frage, ob auf demselben Rechner - und demselben Datenträger - oder via Netzwerk verschoben soll ...

... weil: auf demselben Datenträger eine Datei nicht wirklich verschoben, sondern nur die Startadresse geändert wird ...

... beim verschieben auf andere Datenträger und insbesondere via Netzwerk ist die verfügbare Bandbreite und Dateigröße relevant ...

... ggf. kann man die genutzte Bandbreite [im Netzwerk] begrenzen ...
Pit-80
Pit-80 23.07.2024 um 21:06:29 Uhr
Goto Top
Ah, sorry.

Der Quell- und der Zielordner sind auf dem gleichen Server, gleicher Datenträger.

VG
MirkoKR
MirkoKR 23.07.2024 aktualisiert um 21:52:17 Uhr
Goto Top
Der Quell- und der Zielordner sind auf dem gleichen Server, gleicher Datenträger.

Ich habe jetztmal gegoogelt um die Grundlagen von Kopieren vs. Verschieben und Selbes Laufwerk vs. anderem Laufwerk zu vermitteln ...

Zu meinen Schulungszeiten gehörte das noch zum Standard, aber ich habe auf die schnelle keine brauchbare Quelle gefunden ...

Was wir gelernt haben:

Beim Versvhieben einer Datei auf demselben Laufwerk - c:\Quelle -> C:\Ziel - etc..
... verbleibt die Datei physisch an ihrem Ort und nur die Zuweisung/Adresse im Verzeichnisbaum wird angepasst ...

... sonut sollte das verschieben in deibem Fall (selber Datenträger, selbes Laufwerk) auch für 6000 Dateien nur Sekunden dauern ...

... bei unterschiedlichen Laufwerken Quelle C: zu Ziel D: wird glaube ich "kopiert und gelöscht"

Die Lernressourcen betrafen damals das physische Verschieben und Kopieren in Zusammenhang mit der Behandlung der NTFS-Rechte

Nachtrag: Die Verständnis von [physischen] Datenträgern, [physischen] Partitionen [auch ohne LW-Buchstaben/Links] und [logischen] Laufwerken hat sich mit den steigenden Größen seit den 90ern der Platten ja geändert ...
it-frosch
it-frosch 24.07.2024 um 07:56:35 Uhr
Goto Top
@rubbermann:
danke dir für die interessante Vertiefung des auf den ersten Blick "einfachen Themas".

grüße vom it-frosch
erikro
erikro 24.07.2024 um 09:46:55 Uhr
Goto Top
Moin,

Zitat von @rubberman:
Quick and dirty Lösung: In so einer Polling Schleife ist sowieso irgendeine Form von Sleep eingebaut. Wo, ist grundsätzlich erst mal egal. Im Script von @erikro haben wir das am Ende der do-while Schleife, könnte man aber ebenso zwischen der Definition der $files Variable und der foreach Schleife einbauen. Das eliminiert zwar nicht die Race Condition, aber die Wahrscheinlichkeit dass es jemals crasht tendiert gegen Null.

Da hast Du natürlich völlig recht. Also erst einmal ein Lock auf die Datei:

$quellordner = x:\quelle
$zielordner = x:\ziel

do {

    $files = Get-ChildItem -path $quellordner-file | select -First 50
    foreach($file in $files) {

        $FileStream=""  
        do {
            try {
                $FileStream = [System.IO.File]::Open($file.fullname,'Open','Write')  
                move-item -Path $file.fullname -Destination $zielordner\$file.name
                $FileStream.close()
            }
            catch {
                Start-Sleep -s 5
                $FileStream.close()
            }
        } while($FileStream.CanWrite -eq $false)

    }
    Start-Sleep -Seconds 600

} while($(get-childitem -Path $quellordner -file))

Wieder schnell hingeschrieben ohne Test.

Liebe Grüße

Erik
Pit-80
Pit-80 24.07.2024 um 22:13:44 Uhr
Goto Top
Guten Abend zusammen,

vielen Dank für die vielen Beiträge!

Ich habe heute morgen getestet und anschließend die 6000 Dateien nach und nach, auf dem gleichen Laufwerk, verschoben.
Hierzu habe ich das Skript von it-frosch genutzt. Statt copy-item habe ich das move-item eingesetzt. Nach meinen ersten Tests habe ich die Pause auf 5 Sekunden reduzieren können.
Es ist problemlos durchgelaufen. Es gab kein Auflaufen der Dateien im Zielordner und die Dateien wurden fehlerfrei verarbeitet.

Nochmals vielen Dank für die schnelle Hilfe. 👍

Viele Grüße
Pit-80