Forum: PC-Programmierung [cmd] IF-Abfrage in FOR-Schleife mit Variablen


von Marek N. (Gast)


Lesenswert?

Guten Abend,

ich verzweifele schon seit zwei Tagen an einer eigentlich trivialen 
Kommandozeilenaufgabe.

Es geht darum, dass sich in einem Verzeichnis eine bestimme Anzahl 
Dateien befinden. Eine For-Schleife soll durch diese Dateien iterieren 
und einen Variable setzen. Wenn die Variable eine bestimmte Bedingung 
erfüllt, soll für die nachfolgendne Iterationen was andere mit ihr 
geschehen.

Konkrete Anwendung soll sein, dass in einem Verzeichnis sich mehrere 
unterschiedlich große Dateien befinden. Die Schleife soll die Dateien 
durchgehen, ihre Größe bestimmen und unterwegs kleinere Dateien, als die 
bis jetzt gefundene löschen, so dass am Ende die nur die größte(n) 
Datei(en) übrig bleiben.

Ich habe gelesen, dass für die Auswertung der Variable zur Laufzeit der 
Ausrufezeichen-Operator (!) notwendig ist, aber leider scheitere ich 
daran.

Folgendes Minimalbeispiel verdeutlicht mein Problem:
1
Setlocal EnableDelayedExpansion
2
set idx=0
3
4
for %F in (*.*) do (if !idx! GTR 5 (set /A idx=idx*2) else (set /A idx=idx+1))
5
6
endlocal

Und hier die resultierende Ausgabe:
1
W:\_tmp\temp>for %F in (*.*) do (if !idx! GTR 5 (set /A idx=idx*2) else (set /A idx=idx+1))
2
3
W:\_tmp\temp>(if !idx! GTR 5 (set /A idx=idx*2 )  else (set /A idx=idx+1 ) )
4
1
5
W:\_tmp\temp>(if !idx! GTR 5 (set /A idx=idx*2 )  else (set /A idx=idx+1 ) )
6
2
7
W:\_tmp\temp>(if !idx! GTR 5 (set /A idx=idx*2 )  else (set /A idx=idx+1 ) )
8
3
9
W:\_tmp\temp>(if !idx! GTR 5 (set /A idx=idx*2 )  else (set /A idx=idx+1 ) )
10
4
11
W:\_tmp\temp>(if !idx! GTR 5 (set /A idx=idx*2 )  else (set /A idx=idx+1 ) )
12
5
13
W:\_tmp\temp>(if !idx! GTR 5 (set /A idx=idx*2 )  else (set /A idx=idx+1 ) )
14
6
15
W:\_tmp\temp>(if !idx! GTR 5 (set /A idx=idx*2 )  else (set /A idx=idx+1 ) )
16
7
17
W:\_tmp\temp>(if !idx! GTR 5 (set /A idx=idx*2 )  else (set /A idx=idx+1 ) )
18
8
19
W:\_tmp\temp>(if !idx! GTR 5 (set /A idx=idx*2 )  else (set /A idx=idx+1 ) )
20
9
21
W:\_tmp\temp>(if !idx! GTR 5 (set /A idx=idx*2 )  else (set /A idx=idx+1 ) )
22
10
23
W:\_tmp\temp>(if !idx! GTR 5 (set /A idx=idx*2 )  else (set /A idx=idx+1 ) )
24
11
25
W:\_tmp\temp>(if !idx! GTR 5 (set /A idx=idx*2 )  else (set /A idx=idx+1 ) )
26
12
27
W:\_tmp\temp>(if !idx! GTR 5 (set /A idx=idx*2 )  else (set /A idx=idx+1 ) )
28
13
29
W:\_tmp\temp>(if !idx! GTR 5 (set /A idx=idx*2 )  else (set /A idx=idx+1 ) )
30
14
31
W:\_tmp\temp>(if !idx! GTR 5 (set /A idx=idx*2 )  else (set /A idx=idx+1 ) )
32
15
33
W:\_tmp\temp>(if !idx! GTR 5 (set /A idx=idx*2 )  else (set /A idx=idx+1 ) )
34
16
35
W:\_tmp\temp>(if !idx! GTR 5 (set /A idx=idx*2 )  else (set /A idx=idx+1 ) )
36
17
37
W:\_tmp\temp>(if !idx! GTR 5 (set /A idx=idx*2 )  else (set /A idx=idx+1 ) )
38
18

Wie wir sehen, wird niemals zwischen den Bedingungen umgeschaltet, da 
irgend ein Dödel zu blöd ist, den aktuellen numerischen Wert in die 
IF-Abfrage einzubauen, so dass sie immer als false ausgewertet wird.

Wer ist so nett und verrät mir, wies richtig gemacht wird?

Beste Grüße, Marek

/edit: Der Index wird ja korrekt inkremementiert, aber eigentlich müsst 
bei der sechsten Datei auf "Verdopplung" umgeschaltet werden, aber davon 
bekommt die IF-Abfrage ja nix mit :-(

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Zwar ist der Kommandozeileninterpreter aktueller Windows-Versionen 
deutlich leistungsfähiger als der steinalte DOS-Vorfahr, aber für manche 
Aufgaben ist er eher weniger gut geeignet.

Da jedes auch nur mäßig aktuelle Windows auch VBScript und einen 
Javascript-Dialekt versteht, bietet es sich an, kompliziertere Aufgaben 
damit zu lösen. Oder mit der "Powershell", die aber zumindest bei 
Windows XP noch nicht im Lieferumfang war.

von Rainer V. (rudi994)


Lesenswert?

Windows kenne ich nicht gut, unter DOS mußte man in diesem Fall eine 
Umgebungsvariable in Prozentzeichen einschließen und es gab nur die 
Auswertung von Strings, nicht von Zahlen: IF "%idx%"=="0" ...

Wo steht denn die Sache mit dem Ausrufzeichen-Operator im IF-Befehl?
Ich kann unter "Help IF" nichts finden, nur etwas zu Option /I bei der 
Auswertung numerischer Ausdrücke.

von Marek N. (Gast)


Lesenswert?

Nabend,

also IF unterstützt defininitif auch Zahlen, denn sonst wären die 
Relationen <, <=, >= und > sinnfrei. Das mit dem /I-Parameter muss ich 
gleich mal ausprobieren. Dennoch müsste bei Durchlaufen der For-Schleife 
der aktuelle numerische Wert von idx eingesetzt werden und nicht der 
Variablenname.

Bzgl. Ausrufezeichen: http://ss64.com/nt/delayedexpansion.html

Beste Grüße, Marek

von Rainer V. (rudi994)


Lesenswert?

Aufgrund von "for %F" im o.g. Code nehme ich an, daß dieser Code auf der 
Kommandoebene zeilenweise eingegeben wurde. Ich habe das mal gemacht mit 
gleichem Ergebnis. Daß es nicht wie gewünscht funktioniert, liegt wohl 
daran, daß der Code nicht als Batchdatei ausgeführt wird und sich daher 
SetLocal EnableDelayedExpansion nicht auf nachfolgende Zeilen auswirkt.
In einer Batchdatei gilt SetLocal solange, bis EndLocal auftritt oder 
die Datei beendet ist. http://www.colorconsole.de/console/de/059.htm

O.g. Code als Batchdatei funktioniert! Dazu muß der for-Variablen aber 
ein doppeltes Prozentzeichen vorangehen: for %%F ...

von Marek N. (Gast)


Lesenswert?

Wahnsinn!

Danke Rainer!
Ich hatte das tatsächlich die ganze Zeit nur in der Kommandozeile 
getestet, weil ich das Schritt für Schritt nachvollziehen wollte, was 
passiert. Wer hätte gedacht, dass es da wieder Ausnahmen gibt.
Ok, dann klappt das ja doch, wie geplant.

Vielen Dank noch mal.

Beste Grüße, Marek

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.