benutz3r1993
Goto Top

Batch Array soll der Größe nach Sortiert werden

Liebe Gemeinschaft,

ich bitte vorab um Verzeihung, sollte ich gegen eine Forumsregel (Formatierung, etc.) verstoßen (ist mein aller erster Forums-Beitrag), oder dieses Thema bereits in anderen Themen behandelt worden sein (dann war ich scheinbar zu blöd zum Suchen).

Ich habe bereits dieses Forum (und andere) mehrere Stunden lang durchsucht und konnte die benötigte Information leider nicht finden.

Zu meinem "Problem"...

Ich habe folgenden Code, der mir aus einem NW-Pfad (%pfad_original%) sämtliche *.txt Dateien und deren Namen ausliest und in ein Array speichert:

for %%G in (%pfad_original%*.txt) do (
set filename[!ID!]=%%~G
for %%H in (!ID!) do (
set "new_array[%%H]=!filename[%%H]:~98,8!"  
echo !new_array[%%H]!
)
::set "new_array" 
set /a ID+=1
)

Da ich nur einen Teil des Namens benötige, schneide ich den benötigten Teil aus dem Array aus und speichere die Werte in ein weiteres Array, und bekomme via ECHO folgendes raus:

20210916
20210910
20210915
20210913
20210914



Und an dieser Stelle stehe ich an, irgendwie muss ich dieses Array doch sortieren können, dass es am Ende dann so aussieht:

20210910
20210913
20210914
20210915
20210916



Denn im Endeffekt soll eine ZIP-Datei mit sämtlichen.txt Dateien erstellt werden (der Teil funktioniert bereits) eben mit der Bezeichnung "von_bis.zip"
Von = der kleinste Wert in der Liste (20210910)
Bis = der größte Wert in der Liste (20210916)

Ich habe bereits mehrere Ansätze im Internet gefunden, nur kapiere ich die Durchführung einfach nicht.
Daher dachte ich, vielleicht kann mir das jemanden hier verständlicher erklären, bzw. mich in die richtige Richtung lenken.

Folgenden Ansatz habe ich mir bis jetzt "zusammen gereimt":

set /a "sort_arr=0"  
set /a "sort_arr2=0"  

set /a "element_array1=0"  
set /a "element_array2=0"  
pause
for %%K in (%pfad_original%*.txt) do (
	for %%I in (!sort_arr!) do (
		for %%J in (!sort_arr2!) do (
			if !new_array[%%I]! LEQ !new_array[%%J]! (
				set "help_var=!new_array[%%I]!"  
				set "!new_array[%%I]!=!new_array[%%J]!"  
				set "!new_array[%%J]!=%help_var%"  
			)
		)
		set /a sort_arr2+=1
	)
	set /a sort_arr+=1
)

Nur verläuft der Schleifen-Durchlauf nicht wie ich vermutet habe...scheinbar wird die innere und dann die äußere Schleife gleich darauf durchlaufen...

Schleifen1-Durchlauf1
Schleifen2-Durchlauf1
Schleifen1-Durchlauf2
Schleifen2-Durchlauf2
...
Statt:
Schleifen1-Durchlauf1
Schleifen2-Durchlauf1
Schleifen2-Durchlauf2
Schleifen2-Durchlauf(n-1)

Schleifen1-Durchlauf2
Schleifen2-Durchlauf1
Schleifen2-Durchlauf2
Schleifen2-Durchlauf(n-1)

Kann mich jemand vielleicht auf meinen (massiven) Denkfehler hinweisen, bzw. hat jemand eine bessere Idee um mein Array sortieren zu können?

Für jeden Input bin ich dankbar. face-smile

Ps: Ist sicher mehr als offensichtlich, aber ich bin in diesem Bereich leider erst ein Anfänger.

Vielen Dank vorab

LG

Content-ID: 1283350774

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

Ausgedruckt am: 23.11.2024 um 12:11 Uhr

BirdyB
BirdyB 20.09.2021 aktualisiert um 12:32:28 Uhr
Goto Top
Moin,
warum verwendest du Batch? Mit Powershell wäre das deutlich einfacher zu lösen:
Get-ChildItem -Path "C:\temp" | Sort  

VG
miniversum
Lösung miniversum 20.09.2021 um 12:44:15 Uhr
Goto Top
Hallo,

1. Du solltest wissen, dass es keine Arrays in Batch gibt. Was du da machst sind einfach Variabeln mit der Nummerierung im Namen. Aber das ist hierfür auch erstmal egal und steltl generell kein Problem in Batch dar.
2. Das ist ein einfacher Sortieralgorithmus (da ist dann auch egal das es keine Arrays sind). Hast du den mal mit 3 bis 5 Beispielzahlen getestet? Du kansnt ja problemlos mehrere echo ausgaben einbauen um zu sehen was passiert.
3. Ich würde da mit einer kleinen temporären Hilfsdatei arbeiten. Du schneidest die die Zahlen aus den Dateinamen und schreibst den entsprechenden Wert mit >> direkt in eine temporäre (txt) Datei. Die kannst du dann mit dem SORT befehl sortieren lassen und dann die sortierte Liste in der Datei mit einer For Schleife wieder abarbeiten (das ist das Gleiche was BirdyB oben beschreibt nur in Batch. Dort sieht das dann so aus:
sort TempDatei.txt
Den Sortier- und Abarbeitungsvorgang kanns tud direkt in einander Schachteln. das wird dann so aussehen:
FOR /F "delims=" %%i in ('sort TempDatei.txt') do echo %%i
Benutz3r1993
Benutz3r1993 20.09.2021 um 13:40:28 Uhr
Goto Top
Zitat von @BirdyB:

Moin,
warum verwendest du Batch? Mit Powershell wäre das deutlich einfacher zu lösen:
> Get-ChildItem -Path "C:\temp" | Sort  
> 

VG
Hallo und vielen Dank für die schnelle Antwort face-smile
um ehrlich zu sein habe ich mich mit Powershell noch kaum bis garnicht beschäftigt, ausserdem habe ich bereits mehrere Abläufe (die mein Batch-File können soll) realisieren können, das Einzige was noch fehlt, ist die Werte des "Arrays" zu sortieren...also müsste ich ja wieder bei Null anfangen. :/
Aber sollte ich das nicht hinbekommen, bleibt mir eh nichts anderes übrig (außer meine Niederlage einzugestehen :D )

Zitat von @miniversum:

Hallo,

1. Du solltest wissen, dass es keine Arrays in Batch gibt. Was du da machst sind einfach Variabeln mit der Nummerierung im Namen. Aber das ist hierfür auch erstmal egal und steltl generell kein Problem in Batch dar.
2. Das ist ein einfacher Sortieralgorithmus (da ist dann auch egal das es keine Arrays sind). Hast du den mal mit 3 bis 5 Beispielzahlen getestet? Du kansnt ja problemlos mehrere echo ausgaben einbauen um zu sehen was passiert.
3. Ich würde da mit einer kleinen temporären Hilfsdatei arbeiten. Du schneidest die die Zahlen aus den Dateinamen und schreibst den entsprechenden Wert mit >> direkt in eine temporäre (txt) Datei. Die kannst du dann mit dem SORT befehl sortieren lassen und dann die sortierte Liste in der Datei mit einer For Schleife wieder abarbeiten (das ist das Gleiche was BirdyB oben beschreibt nur in Batch. Dort sieht das dann so aus:
sort TempDatei.txt
Den Sortier- und Abarbeitungsvorgang kanns tud direkt in einander Schachteln. das wird dann so aussehen:
FOR /F "delims=" %%i in ('sort TempDatei.txt') do echo %%i

Auch dir ein Hallo und danke für die schnelle Antwort face-smile
An sich ist deine Methode nicht schlecht, das Problem ist nur, dass ich in meinem kompletten Code sämtliche .txt Files in meinem Ordner auslese und deren Namen in das "Array" ablege...und würde ich da noch eine weitere .txt Datei erstellen, dann würde diese auch ausgelesen werden.

Das mit der Hilfsvariable habe ich bereits getestet, das Problem ist nur, dass die Schleifen nicht so durchlaufen, wie ich es vermutet habe.

for %%K in (%pfad_original%*.txt) do (
	for %%I in (!sort_arr!) do (
		for %%J in (!sort_arr2!) do (
			if !new_array[%%I]! LEQ !new_array[%%J]! (
				set "help_var=!new_array[%%I]!"  
				set "!new_array[%%I]!=!new_array[%%J]!"  
				set "!new_array[%%J]!=%help_var%"  
			)
                       echo Array_innen %%J.Schleife:!new_array[%%J]!
		)
                echo Array_aussen %%I.Schleife:!new_array[%%I]!
		set /a sort_arr2+=1
	)
	set /a sort_arr+=1
)

Dadurch, dass die äußere Schleife direkt nach der inneren durchläuft sind die Werte
!new_array[%%I]!und !new_array[%%J]! immer gleich, dadurch erfüllt sich die IF-Anweisung nie.

Bsp: Mein Array hat folgende Werte:

20210916
20210910
20210915
20210913
20210914


Gebe ich mir das Element an der Stelle %%J in der inneren Schleife und Element an der Stelle %%I in der äußeren Schleife aus (wie im Code ersichtlich), erhalte ich folgendes via Echo:

Das System kann das angegebene Laufwerk nicht finden. (Wieso die Meldung erscheint, verstehe ich auch nicht)
Array_innen 0.Schleife:20210916
Array_aussen 0.Schleife:20210916
Drücken Sie eine beliebige Taste . . .
Das System kann das angegebene Laufwerk nicht finden.
Array_innen 1.Schleife:20210910
Array_aussen 1.Schleife:20210910
Drücken Sie eine beliebige Taste . . .
Das System kann das angegebene Laufwerk nicht finden.
Array_innen 2.Schleife:20210915
Array_aussen 2.Schleife:20210915
...
Benutz3r1993
Benutz3r1993 20.09.2021 aktualisiert um 13:50:35 Uhr
Goto Top
Hier mal den gesamten (momentan aktiven) Code meines Batch-Files:

@echo off

::Setzen der Pfade
set kuerzel=""  
set pfad_original=****
set pfad_zip_file=****
set pfad_pp1=****

::Check, welcher User, damit das richtige Kürzel gesetzt wird
IF "%username%" == "***" ( set kuerzel=*** )  
IF "%username%" == "***" ( set kuerzel=*** )  
IF "%username%" == "***" ( set kuerzel=*** )  
IF "%username%" == "***" ( set kuerzel=*** )  
IF "%username%" == "***" ( set kuerzel=*** )  

::Befüllen des Arrays, damit der erste und letzte Eintrag ausgelesen werden kann -> für das ZIP File
setlocal enableDelayedExpansion
set /a "ID=0"  

for %%G in (%pfad_original%*.txt) do (
    set filename[!ID!]=%%~G
	for %%H in (!ID!) do set "new_array[%%H]=!filename[%%H]:~98,8!"  
	::set "new_array" 
	set /a ID+=1
)
set /a "sort_arr=0"  
set /a "sort_arr2=0"  

set /a "element_array1=0"  
set /a "element_array2=0"  
pause
for %%K in (%pfad_original%*.txt) do (
	for %%I in (!sort_arr!) do (
		for %%J in (!sort_arr2!) do (
			if !new_array[%%I]! LEQ !new_array[%%J]! (
				REM set "help_var=!new_array[%%I]!"  
				REM set "!new_array[%%I]!=!new_array[%%J]!"  
				REM set "!new_array[%%J]!=%help_var%"  
			)
			echo Array_innen %%J.Schleife:!new_array[%%J]!
		)
		echo Array_aussen %%I.Schleife:!new_array[%%I]!
		set /a sort_arr2+=1
	)
	pause
	set /a sort_arr+=1
)
BirdyB
BirdyB 20.09.2021 um 14:12:38 Uhr
Goto Top
Zitat von @Benutz3r1993:

Zitat von @BirdyB:

Moin,
warum verwendest du Batch? Mit Powershell wäre das deutlich einfacher zu lösen:
>> Get-ChildItem -Path "C:\temp" | Sort  
>> 

VG
Hallo und vielen Dank für die schnelle Antwort face-smile
um ehrlich zu sein habe ich mich mit Powershell noch kaum bis garnicht beschäftigt, ausserdem habe ich bereits mehrere Abläufe (die mein Batch-File können soll) realisieren können, das Einzige was noch fehlt, ist die Werte des "Arrays" zu sortieren...also müsste ich ja wieder bei Null anfangen. :/
Aber sollte ich das nicht hinbekommen, bleibt mir eh nichts anderes übrig (außer meine Niederlage einzugestehen
Moin,
ich würde das erstmal nicht als Niederlage verbuchen... Powershell macht eben viele Arbeitsabläufe deutlich einfacher und übersichtlicher. Batch bietet eben viele Features nicht und ist auch eher so 90er face-wink
Ich behaupte, dass du die Abläufe in deinem jetzigen Code mit der Hälfte der Zeilen in PS hinbekommst.
Und so schwer ist PS jetzt auch nicht... Schau z.B. mal hier: https://docs.microsoft.com/de-de/powershell/scripting/learn/tutorials/00 ...
Das nur so als Anregung von meiner Seite... Zu deinem Batch-Problem kann ich leider nicht viel beitragen...
VG
149569
149569 20.09.2021 aktualisiert um 15:13:56 Uhr
Goto Top
@echo off
set "pfad_original=E:\Quelle"  
for /f "delims=" %%a in ('powershell -EP Bypass -C "$f = ls -literalpath '%pfad_original%' -File -Filter *.txt | %%{$_.BaseName.substring(98,8)} | sort; $f + '_' + $f[-1] + '.zip'"') do set "outputname=%%a"  
echo %outputname%
miniversum
miniversum 20.09.2021 um 15:42:15 Uhr
Goto Top
Hallo,

Zitat von @Benutz3r1993:

An sich ist deine Methode nicht schlecht, das Problem ist nur, dass ich in meinem kompletten Code sämtliche .txt Files in meinem Ordner auslese und deren Namen in das "Array" ablege...und würde ich da noch eine weitere .txt Datei erstellen, dann würde diese auch ausgelesen werden.

Der "Trick" ist, diese temporäre Datei entweder nicht .txt zu nennen oder in einem anderen verzeichniss zu speichern (z.B. %temp%) oder beides...

Spontan, ohne getestet zu haben, könnte es auch helfen das
set "!new_array[%%J]!=%help_var%"
in
set "!new_array[%%J]!=!help_var!"
zu ändern.

Was immer (wirklich IMMER) kommt, wenn du nicht genau sehen kannst woran es hängt ist, das echo off in der ersten Zeile durch ein echo on zu ersetzen, bzw. es auszukommentieren. Dann siehst du detailiert alles was verarbeitet wird, inklusive erzeugter Variabelnnamen und was du denen zugewiesen wird. Das ist eiger der großen vorteile bei Batch die andere Skriptsprachennicht bieten, variabeln werden immer erst aufgelöst udn dann interpretiert (außer absichtlich die delayed expansion). Damit kannst du wunderbar dynamisch Code zur Laufzeit erzeugen oder halt, wie hier, direkt als ausgabe sehen was getan wird.
Benutz3r1993
Benutz3r1993 20.09.2021 um 15:50:07 Uhr
Goto Top
Zitat von @BirdyB:

Zitat von @Benutz3r1993:

Zitat von @BirdyB:

Moin,
warum verwendest du Batch? Mit Powershell wäre das deutlich einfacher zu lösen:
>>> Get-ChildItem -Path "C:\temp" | Sort  
>>> 

VG
Hallo und vielen Dank für die schnelle Antwort face-smile
um ehrlich zu sein habe ich mich mit Powershell noch kaum bis garnicht beschäftigt, ausserdem habe ich bereits mehrere Abläufe (die mein Batch-File können soll) realisieren können, das Einzige was noch fehlt, ist die Werte des "Arrays" zu sortieren...also müsste ich ja wieder bei Null anfangen. :/
Aber sollte ich das nicht hinbekommen, bleibt mir eh nichts anderes übrig (außer meine Niederlage einzugestehen
Moin,
ich würde das erstmal nicht als Niederlage verbuchen... Powershell macht eben viele Arbeitsabläufe deutlich einfacher und übersichtlicher. Batch bietet eben viele Features nicht und ist auch eher so 90er face-wink
Ich behaupte, dass du die Abläufe in deinem jetzigen Code mit der Hälfte der Zeilen in PS hinbekommst.
Und so schwer ist PS jetzt auch nicht... Schau z.B. mal hier: https://docs.microsoft.com/de-de/powershell/scripting/learn/tutorials/00 ...
Das nur so als Anregung von meiner Seite... Zu deinem Batch-Problem kann ich leider nicht viel beitragen...
VG

Grüß dich Birdy,

also ich hab deinen Befehl jetzt mal via PowerShell probiert:

Mode LastWriteTime Length Name
------------- ------ ----
-a---- 10.09.2021 12:00 50181 64080007_20210916wr.txt
-a---- 10.09.2021 12:00 50181 64080347_20210910wr.txt
-a---- 10.09.2021 12:00 50181 64081007_20210915wr.txt
-a---- 13.09.2021 13:49 85342 64161510_20210913wr.txt
-a---- 14.09.2021 14:08 114107 64205377_20210914wr.txt
-a---- 20.09.2021 15:39 3479 meinfile.cmd


Und da habe/hätte ich das gleiche Problem, da in diesem Beispiel der Wert der ersten Datei scheinbar am kleinsten ist, bekomme ich in meinem Batch-File 20210916 als Array ausgelesen, daher war mein Gedanke, nur den Teil auszuschneiden und demensprechend zu sortieren
Benutz3r1993
Benutz3r1993 20.09.2021 um 17:40:58 Uhr
Goto Top
Zitat von @miniversum:

Hallo,

Zitat von @Benutz3r1993:

An sich ist deine Methode nicht schlecht, das Problem ist nur, dass ich in meinem kompletten Code sämtliche .txt Files in meinem Ordner auslese und deren Namen in das "Array" ablege...und würde ich da noch eine weitere .txt Datei erstellen, dann würde diese auch ausgelesen werden.

Der "Trick" ist, diese temporäre Datei entweder nicht .txt zu nennen oder in einem anderen verzeichniss zu speichern (z.B. %temp%) oder beides...

Spontan, ohne getestet zu haben, könnte es auch helfen das
set "!new_array[%%J]!=%help_var%"
in
set "!new_array[%%J]!=!help_var!"
zu ändern.

Was immer (wirklich IMMER) kommt, wenn du nicht genau sehen kannst woran es hängt ist, das echo off in der ersten Zeile durch ein echo on zu ersetzen, bzw. es auszukommentieren. Dann siehst du detailiert alles was verarbeitet wird, inklusive erzeugter Variabelnnamen und was du denen zugewiesen wird. Das ist eiger der großen vorteile bei Batch die andere Skriptsprachennicht bieten, variabeln werden immer erst aufgelöst udn dann interpretiert (außer absichtlich die delayed expansion). Damit kannst du wunderbar dynamisch Code zur Laufzeit erzeugen oder halt, wie hier, direkt als ausgabe sehen was getan wird.

Hallo miniversum,

also ich habe es nun mit deinem "Trick" mit der zusätzlichen temp.txt versucht und es funktioniert super!!
In deiner Sort Schleife lege ich die Werte in ein "Array" ab und habe nun Zugriff auf die richtigen Elemente, so wie ich es brauche.

Vielen Dank für deinen Input, oftmals braucht man nur eine andere Sichtweise.

Auch allen anderen möchte ich für eure Zeit und eure Mühen danken. face-smile

Ganz liebe Grüße
Benutz3r1993
Lösung Benutz3r1993 20.09.2021 um 17:47:18 Uhr
Goto Top
Falls es noch jemand brauchen sollte, hier der vollendete Code (für dieses Problem):
%pfad_original% ist der Pfad auf dem die .txt Dateien liegen

for %%G in (%pfad_original%*.txt) do (
    set filename[!ID!]=%%~G
	for %%H in (!ID!) do  (
		set "new_array[%%H]=!filename[%%H]:~98,8!"  
REM 'Pfad' mit dem richtigen Pfad austauschen, wo die TempDatei erzeugt werden soll  
		echo !new_array[%%H]! >> 'Pfad'\TempDatei.txt  
	)
	set /a ID+=1
	)

set /a "final_id=0"  
FOR /F "delims=" %%i in ('sort 'Pfad'\TempDatei.txt') do (  
	for %%J in (!final_id!) do ( 
		set sort_array[!final_id!]=%%i
		echo !sort_array[%%J]!
	)
	set /a final_id+=1
)
149569
149569 20.09.2021 um 20:34:16 Uhr
Goto Top
Und ohne extra Textdatei steht's schon oben 😉
Benutz3r1993
Benutz3r1993 21.09.2021 um 10:26:36 Uhr
Goto Top
Zitat von @149569:

Und ohne extra Textdatei steht's schon oben 😉

Hallo Hacktor,

ich habe dich nicht überlesen, nur hatte ich gestern leider keinen Kopf mehr zum Antworten :/
hoffe du bist nicht böse. face-smile
Auch dir ein riesen Dankeschön, für deinen Input...habe gestern deine Version noch kurz getestet, dürfte aber zu blöd sein diesen Befehl richtig auszuführen.
Hättest du vielleicht die Zeit und die Lust mir diesen Befehl zu erklären? (Falls nicht, versuch ich es zu googeln)

Trotzdem vielen Dank!

LG
149569
149569 21.09.2021 aktualisiert um 11:58:56 Uhr
Goto Top
Zitat von @Benutz3r1993:

Hättest du vielleicht die Zeit und die Lust mir diesen Befehl zu erklären? (Falls nicht, versuch ich es zu googeln)

Ist einfach nur Powershell in ne Batch eingebaut, nichts besonderes.