Batch Knifflige Aufgabe zum Programmieren

pat87

Newbie
Registriert
Mai 2014
Beiträge
4
Hallo,

Ich habe eine knifflige Aufgabe für euch und möchte mal eure Meinung dazu hören ob dies überhaupt so möglich ist.

Es Geht um ein System welches Messungen durchführt und dann dafür jeweils eine Datei erstellt. Der Name der Datei ist z.B.
"P2070_128_74_4037_2014_05_08 01_21-58.xml wobei folgende Informationen enthalten sind:
P2070 = Produkt, hierbei gibt es P2070, P2069, P2064, P2065
128 = Produktionstag
7 = Interne Bezeichnung hierbei gibt es 1,4,7
4 = für das Jahr 2014
4 = Interne Bezeichnung hierbei gibt es 1,2,3,4,6,7,8,9
037 = Stückzahl Teil

2014_05_08 = Datum der Messung
01_21-58 = Zeit der Messung

Jetzt kann es vorkommen dass das System 6 mal das Selbe Produkt misst und somit die Datei mit dem Name "P2070_128_74_4037_2014_05_08 01_21-58.xml mehrmals vorhanden ist.
Nur das Datum und die Zeit am Schluss ändern sich und ich bräucht immer nur die aktuellste und die ältere Datei sofern die Zahlen und Zeichen davor alle gleich sind, kann gelöscht werde.
Das ist schwer da die Zahlen sich ändern können somit müsste man zwei Dateien finden bei denen die ersten 14 Zahlen stimmen.

Hier mal noch ein vild von dem Ordner wo alles zusammen läuft, dort kann man auch erkennen wie oft Datensätze mehrfach vorkommen.

Foto.JPG
 
Vielleicht ist es möglich, von Batchprogrammierung habe ich wenig Ahnung. Wäre es in deinem Fall auch möglich es mit einer anderen Sprache zu lösen, Python oder C# z.B.? Da wäre es nicht schwierig.
 
Da Batch in meinen Augen ein Krampf ist empfehle ich als erstes mal sowas wie Perl/Python oder wenigstens die Powershell.
In Pseudocode würde ich folgenden Ablauf vorschlagen:
Code:
lastPrefix = ""
lastFile = ""
foreach file {
    currPrefix = substr(file, x, y)
    if currPrefix == lastPrefix {
        remove lastFile
    }
    lastPrefix = currPrefix
    lastFile = file
}
Dabei gehe ich davon aus, dass die Dateien alphanumerisch sortiert durchlaufen werden. Wenn ich das richtig sehe sind die Dateinamen von neueren Dateien > als die von alten.
Das würde also immer die vorhergehende Datei löschen wenn die aktuelle den selben Präfix hat. Das kann man sicher auch mit Batch irgendwie umsetzen. Da kenne ich mich aber nicht mit aus und würde dich dann an den nächsten oder dich selbst verweisen.
 
Mit Powershell wäre das garnicht so schwer. Kannst du die einsetzen? (ab Win 7 standartmäßig dabei).

Das Muster ist ja ziemlich konstant, daher sollte es einfach sein das zu parsen.
 
Abgesehen von einer vernünftigen Programmiersprache: Warum existiert eine solche Steinzeitlösung überhaupt noch?

Eine Datenbank dafür wäre deutlich eleganter, praktischer, effizienter, ...
 
ascer schrieb:
Eine Datenbank dafür wäre deutlich eleganter, praktischer, effizienter, ...
Schön fürs nächste Mal, nützt ihm jetzt aber überhaupt nichts.

@ TE: Quick'n'Dirty in PowerShell:
Code:
$files = @{}
gci . -Filter "*.xml" | % {
    $file = $_
    $filename = $file.BaseName

    $parts = $filename -split "[ _-]"

    if( $parts.Count -eq 10 )
    {
        $produkt = $parts[0]
        $produktionstag = $parts[1]
        $interne_bezeichnung = $parts[2][0]
        $jahr = $parts[2][1]
        $interne_bezeichnung2 = $parts[3][0]
        $stueckzahl = ($parts[3].ToString()).SubString( 1 )
        $datum = "$($parts[4])-$($parts[5])-$($parts[6])"
        $zeit = "$($parts[7])-$($parts[8])-$($parts[9])"

        $fn = "$produkt-$produktionstag-$interne_bezeichnung-$jahr-$interne_bezeichnung2-$stueckzahl"
        if( !$files.ContainsKey( $fn ) )
        {
            $files[$fn] = @()
        }
        $files[$fn] += "$datum-$zeit"
    }
}

$sorted = @{}

foreach( $Key in $files.Keys )
{
    $Value = $files[$Key]

    $sorted[$Key] = ($Value | sort -Descending)
}

$matched = @()

foreach( $Key in $sorted.Keys )
{
    $Value = $sorted[$Key]
    switch( $Value.GetType().Name )
    {
        "String"
        {
            $matched += "$Key-$Value"
        }
        "Object[]"
        {
            $matched += "$Key-$($Value[0])"
        }
    }
}

$matched | % {
    $match = $_
    $os = ($match -split "[ _-]")

    $fn = "$($os[0])_$($os[1])_$($os[2])$($os[3])_$($os[4])$($os[5])_$($os[6])_$($os[7])_$($os[8]) $($os[9])_$($os[10])-$($os[11]).xml"
    if( -not (Test-Path ".\latest") )
    {
        New-Item -ItemType container ".\latest"
    }
    Copy-Item $fn ".\latest\$fn"
}
Einfach ins jeweilige Verzeichnis mit den Dateien legen und von dort aus ausführen. Das Script geht das aktuelle Verzeichnis durch, durchsucht das Schema und kopiert dir die neuesten Dateien jeweils ins Verzeichnis .\latest.
 
ascer schrieb:
Abgesehen von einer vernünftigen Programmiersprache: Warum existiert eine solche Steinzeitlösung überhaupt noch?

Eine Datenbank dafür wäre deutlich eleganter, praktischer, effizienter, ...

Das kann der Schlaumeier natürlich aus der Ferne einschätzen ... :freak: Hilfe für den TE: 0.001%

Mit folgendem Quick&Dirty Powershell-Skript (in eine .ps1 Datei kopieren, Aufruf "datei.ps1 -path SUCHPFAD") bekommt man ein Array von Objekten mit den Eigenschaften "Product","Date","File":

Code:
param (
	$Path = $(".")
)

$files = ls ($Path.TrimEnd("\")+"\P*.XML");
$items = @();
foreach ($file in $files)
{
	$name = $file.Name;
	$product = ($name.split("_")[0..3] -join "-");
	$date = $date = ($name.Split("_")[4..7] -join ":").TrimEnd(".xml").Replace("-",":");
	$item = @{"Product"=$product; "Date"=$date; "File"=$file};
	$obj = New-Object System.Object
	$obj | Add-Member -type NoteProperty -name Product -value $product
	$obj | Add-Member -type NoteProperty -name Date -value $date
	$obj | Add-Member -type NoteProperty -name File -value $file
	$items += $obj;
}
$items;

Anschließend kannst du das mit den üblichen One-Linern verarbeiten, z.B.

Code:
$ProductEntrys = datei.ps1 -Path D:\xyz | sort Date,Product -Descending | group Product
....
Ergänzung ()

Oh ein wenig zu spät, aber in einem decken sich die Beiträge: Quick&Dirty :king:
 
DaZpoon schrieb:
Oh ein wenig zu spät, aber in einem decken sich die Beiträge: Quick&Dirty :king:

Da musste ich auch schmunzeln beim Lesen^^
Ich hoffe das Thema ist damit gegessen und es muss nicht wirklich Batch sein. Da bekommt man immer Augenkrebs, wenn man den Code sieht (ok, zumindest ich).
 
Zum Thema Datenbank:

Yuuri schrieb:
Schön fürs nächste Mal, nützt ihm jetzt aber überhaupt nichts.

@ TE: Quick'n'Dirty in PowerShell (...)

DaZpoon schrieb:
Das kann der Schlaumeier natürlich aus der Ferne einschätzen ... :freak: Hilfe für den TE: 0.001%

Mit folgendem Quick&Dirty Powershell-Skript (...)

Freezedevil schrieb:
Da musste ich auch schmunzeln beim Lesen^^
Ich hoffe das Thema ist damit gegessen und es muss nicht wirklich Batch sein. Da bekommt man immer Augenkrebs, wenn man den Code sieht (ok, zumindest ich).

Es geht hierbei ja nicht darum, etwas aus der Ferne einzuschätzen, dass brauch man bei der Lösung auch gar nicht. Jedem von uns mit halbwegs vernünftigen Programmierkenntnissen ist doch wohl direkt aufgefallen, dass es dafür mit gegebenen Mitteln nur eine "Quick&Dirty"-Implementierung gibt.
Einige von uns merkten sogar an, wie sehr zum Kotzen solchen Sachen sind.

Da es um Produkte geht, schätze ich mal, dahinter steht ein professionelles Umfeld. Wo ist denn jetzt die Wartbarkeit bei solch einer Lösung?
Das einzige, was man jetzt getan hat, ist eine aktuell schon "murksige" Lösung (einzelne Dateien usw.), bei der jeder von uns unabhängig voneinander schon das "Dirty"-Gefühl hatte, mit noch mehr "Murks" aufzubohren, damit es "irgendwie" funktioniert. Quick'n'Dirty eben, das hat es so an sich.

Sowas gehört, meiner Meinung nach, aber nicht in ein professionelles Umfeld...und mal ganz ehrlich, so unendlich viel länger würde eine vernünftige Neuimplementation mit einer Datenbank auch nicht dauern. Diese wäre dann auch wartbar, würde in der Zukunft keine Probleme machen, falls nochmal was geändert werden muss usw. usf.

Gerade im professionellem Umfeld, aber auch so überhaupt, finde ich es schon wichtig, den Fragenden auf Probleme und vor allem auf eine qualitativ gute Lösung hinzuweisen, um zumindest mal drüber geredet zu haben, was der beste oder zumindest ein guter Lösungsweg ist.

Hier wurde ihm jetzt nur der einfachste/schnellste Weg nach dem Quick'n'Dirty-Prinzip zusammengebaut. Das bringt ihm doch auch nicht viel, außer das es jetzt erstmal läuft. Vorerst.
D.h. jetzt ist der Mehrgewinn für den TE doch auch nur, dass er copy&paste benutzen kann und es danach wieder in einer Schublade verschwinden lässt. Bis es die nächsten, noch größeren Probleme gibt.
 
Zuletzt bearbeitet:
ascer schrieb:
Hier wurde ihm jetzt nur der einfachste/schnellste Weg nach dem Quick'n'Dirty-Prinzip zusammengebaut. Das bringt ihm doch auch nicht viel, außer das es jetzt erstmal läuft. Vorerst.
Ja, es wurde eine Lösung, für ein gegebenes Problem präsentiert. Eine Neuimplementierung (wenn überhaupt möglich!) ist auf jeden Fall zehn Mal teurer, wenn nicht sogar von der Firma selbst einige Mitarbeiter dafür abgestellt werden müssen. Warum also nicht ein kleines Script dafür hernehmen, das Gegebenes gut wartbar einsortiert? An dem Script hab ich kumulativ vielleicht fünf Minuten gesessen (hatte auf Arbeit ja auch noch anderes zu tun, deswegen halt ein wenig länger mit dem Post). Hättest du hierbei nun eine Möglichkeit für die Datenbank geschrieben, inkl. Schreiben + Weiterverarbeitung? Woher weißt du, für welche Programme die Dateien verwendet werden? Evtl. werden diese zum Abgleichen per FTP auf einen Server transferiert und dort wiederum eingelesen und ausgewertet?! Vielleicht werden die Dateien als Anhänge in Mails versendet oder es wird auf eine Art Serienbrief Rechnungen geschrieben, ... Ich hab keine Ahnung was damit passiert und es interessiert mich auch nicht. Der TE hatte ein Problem, was man fix in wenigen Minuten mit einem Script umgehen kann -> Problemstellung schnell und einfach gelöst.

Ich stimm dir insofern zu, dass eine Datenbank wohl die bessere Lösung wäre. Allerdings kennst du die Umstände nicht (wie gesagt, evtl. gibts dort ne Kette an Programmen, die evtl. nichts mit einer DB-Anbindung anfangen können), ergo ist der Vorschlag einer Neuimplementation Unfug.
 
Weil du immer "professionelles Umfeld" erwähnst: Schonmal dort gearbeitet? Worum geht es denn im professionellen Umfeld? Richtig, um Geld. Und es zählt mehr und mehr die Devise, Zeit^2 = Geld. Und da passt man sich einfach den Gegebenheiten an statt bei jedem bisschen gleich alles auf den Haufen zu werfen und neu zu machen.
Und so wie ich es verstanden habe kommen die Messdateien/Ergebnisse aus irgend einem anderen System, worauf man meist keinen Einfluss hat. Eben dieses Skript kann ja erst die Schnittstelle zu einer Datenbank sein. Außerdem kannst du kaum beurteilen was sich genau in den XML-Dateien befindet. Je nach Datenbestand bläht das eine Datenbank so sehr auf dass das oftmals viel schwieriger zu pflegen ist, vor allem da (vor allem relationale) Datenbanken ja nun nicht gerade flexibel sind. Daher ist eine dateibasierte Lösung hier wahrscheinlich deutlich simpler.

Du kannst dich natürlich gern selbständig machen und als Freelancer in die Unternehmen gehen mit der Botschaft: "Ich baue euch alles um damit es technisch hübsch ist, der Anwender bekommt davon nix mit". Mal sehen wer dafür Geld ausgibt.

So, genug gemeckert. :cool_alt:
 
@ascer

Im "professionellen Umfeld", also in Fabriken, ist so etwas nach meiner Erfahrung eher typisch. ;)

So etwas muss bereits bei der Planung der Fabrik berücksichtigt werden (z.B. im Rahmen eines Process Control System für die ganze Fabrik), um Schnittstellen für die einzelnen Maschinen zum Datenaustausch (in Form von Telegrammen) definieren zu können, um die Daten dann zentral in einer Datenbank sammeln zu können. Wenn so etwas nicht geschieht, dann landen die Messdaten eben in irgendwelchen Dateien.

Nachträgliche Lösungen können dann eigentlich nur noch Quick'n'Dirty sein. Für manche Fabriken ist das auch vollkommen ausreichend.

Das nur kurz als Anmerkung, da das Problem bereits gelöst wurde.
 
Zuletzt bearbeitet:
Hallo danke für die vielen wertvollen Anregungen.
Es geht in der Tat um ein Professionelles Umfeld. Daher kann ich auch nichts neu schreiben oder besser machen.
Ich bekomme die Dateien aus einer geschlossenen Messmaschine und kann nichts an der Art wie sie mir die Messmaschine zur Verfügung stellt ändern. Ich bin ja schon froh das dieses ding mir überhaupt was zur Verfügung stellt :lol:

Der Vorschlag von Yuuri war schon sehr gut. Hab es auch mit PowerShell zum laufen bekommen und kann somit auf Batch verzichten.
Habe ein wenig umgeschrieben das die Datei nicht verschoben wird sondern gelöscht.

Habe jetzt nur noch drei kleine Probleme:

1. Ich will nicht die neuste Datei verschieben, sondern vielleicht einfach die ältere aus dem Ordner löschen ( ist glaub das einfachste )
-( ist glaub das einfachste )

2. und dies auch nur wenn die Datei Doppelt vorhanden ist. Hab nämlich das Problem wenn ich das Programm mehr mal´s ausführe immer eine Datei gelöscht/verschoben wird und wenn die Datei nur einmal vorhanden ist wird diese Gelöscht.
- Also brauche ich was, was die ältere Datei immer löscht wenn diese Doppelt vorhanden ist und sonst nicht.
( ist glaub das schwerste meine Probleme )

3. Das Programm sollte dann wenn 1. und 2. funktioniert dauerhaft mit einer Schleife ausgeführt werden. z.B einmal alle 2 Minuten.
-( ist glaub auch einfach für euch )

Wenn wir das noch hin bekommen bin ich glücklich und alle Anforderungen wurden erfüllt. :lol: :jumpin: :love:
 
Hm das Script steht ja schon. Du kannst auch einfach mittels Remove-Item *.xml alle überflüssigen Messungen löschen und dann die Dateien aus latest\ in den aktuellen Ordner verschieben (Move-Item latest\*.xml .). Dann hast du es auch einfach gefiltert und nur die neuesten Dateien im Verzeichnis liegen. Einfach die zwei Befehle ans Ende meines Scriptes hängen.
 
Nochmal zur Verständnis du würdest das Script so lassen und die Dateien in den Ordner latest verschieben , dann all die anderen Dateien löschen und dann die Dateien aus latest wieder zurück in den aktuellen Ordner.

Klingt sehr einfach und genial und das Vergleichen ob was doppelt ist fällt weg. Warum fällt mir sowas nicht ein :mad:

Fehlt nur noch die Dauerrschleife hab mal was gelesen über "goto" aber scheinbar ist das in Programmier Kreisen etwas verpönt. Und dann dachte ich an einen einfachen Start-stop von 2min Befehl oder wie löst man das am schönsten
 
Zuletzt bearbeitet:
Na, nix mit Dauerschleife. Geh dazu in die Aufgabenplanung und leg dafür ne neue Aufgabe an.

Trigger = nach einem Zeitplan, einmal, wiederholen alle x Minuten, für die Dauer von Sofort
Aktion = das Script auswählen, Start in dem Verzeichnis, wo die XML-Dateien liegen bzw. das Script selbst
Bedingungen = alle Häkchen entfernen
Einstellungen = nur "Ausführung bei Bedarf zulassen" aktiviert lassen

Den Task evtl. als eigenen User starten lassen, falls an dem PC gearbeitet wird, sonst öffnet sich dann alle paar Minuten immer die Konsole. Wenn du das unter einem anderen User laufen lässt, siehst du die Konsole gar nicht mehr. Den User einfach über die Verwaltung fix erstellen, dann läuft das.
 
Klingt super. Ich werde das morgen mal probieren und dann hier berichten.
 
Zurück
Oben