friemler
Goto Top

Tutorial zur FOR-Schleife

Da hier im Forum immer wieder mal die Frage nach einem Tutorial für die FOR-Schleife in Batch-Skript auftaucht und die Suche bei Google auch keine wirklich befriedigenden Ergebnisse liefert, habe ich mich nun entschlossen, selbst ein solches Tutorial zu schreiben. Ich werde mich bemühen, auf alle Details dieses komplexen Befehls einzugehen. Da ich jedoch kein geübter Verfasser solcher Tutorials bin, sind konstruktive Kritik und Verbesserungsvorschläge willkommen.

Dieses Tutorial richtet sich vor allem an interessierte Neulinge in Sachen Batchprogrammierung, denen die Hilfe zum FOR-Befehl nur ungenügende Informationen liefert. Gerade die Variante FOR /F bietet viele Möglichkeiten, die jedoch sehr knapp bzw. verwirrend beschrieben werden. Wichtige Details fehlen ganz.

Bei den Erklärungen der einzelnen Varianten des FOR-Befehls werden, wie allgemein üblich, optionale Teile in eckigen Klammern eingeschlossen dargestellt.



back-to-topAllgemeines zur FOR-Schleife

Die FOR-Schleife gibt es in mehreren Varianten.

  • Die Urform und ihre Weiterentwicklungen
FOR [/D] [/R [[Laufwerk:]Pfad]] %Variable IN (Satz) DO Befehl [Parameter]
  • Variante zur Erzeugung von Zahlenfolgen, funktioniert wie eine FOR-Schleife in normalen Programmiersprachen
FOR /L %Variable IN (Start,Schritt,Ende) DO Befehl [Parameter]
  • Mehrzweck-Variante
FOR /F ["Optionen"] %Variable IN (Ausdruck) DO Befehl [Parameter]
Bei allen Varianten wird eine Laufvariable benutzt, die entgegen der üblichen Regel für CMD-Umgebungsvariablen nur mit einem vorangestellten Prozentzeichen gekennzeichnet wird. Wird die FOR-Schleife in Batchfiles verwendet, muss dieses Prozentzeichen verdoppelt werden.

Als Variablennamen dürfen nur einzelne Zeichen verwendet werden. Zwar sind sehr viele der druckbaren ASCII-Zeichen als Variablennamen erlaubt, man sollte sich aber auf die Verwendung von Buchstaben (A-Z oder a-z) beschränken.

Bei den Variablennamen wird zwischen Groß- und Kleinschreibung unterschieden. Die Variable %I ist also etwas anderes als %i.

Möchte man mehr als einen Befehl in der FOR-Schleife ausführen lassen, kann man wie üblich die Befehle mit dem Operator & verketten oder (in Batchfiles) die Befehlszeile durch die Verwendung von Klammern auf mehrere Zeilen "verlängern":
FOR %%Variable IN (Satz) DO (
  Befehl1 [Parameter]
  Befehl2 [Parameter]
)
Da diese Notation in Batchfiles verwendet wird, hier auch die Kennzeichnung der Laufvariablen durch zwei Prozentzeichen. Aber Achtung: Eine solche Konstruktion wird vom Befehlszeileninterpreter als eine Zeile betrachtet! Was bedeutet das für den Programmierer? Befehle, die mit Variablen arbeiten, die in dem geklammerten Block verändert werden, funktionieren nicht wie gewünscht. Das liegt an der Art und Weise, wie der Befehlsinterpreter Befehlszeilen auswertet, übersetzt und ausführt. Stichwort: Erweiterung von Variablen. Damit ist das Ersetzen einer Variable in einem Ausdruck durch ihren Wert gemeint.


back-to-topExkurs (verzögerte) Variablenerweiterung
Das Problem mit der Variablenerweiterung tritt auch bei anderen Ausdrücken auf, in denen eine Befehlszeile durch die Verwendung von Klammern verlängert wurde, also z.B. auch beim IF-Befehl. Hier ein Beispiel:
setlocal

set "users=C:\Users"  

set "home="  
set /p "home=Geben Sie den Benutzernamen ein: "  

if not "%home%"=="" (  
  set "op_dir=%users%\%home%"  
  dir "%op_dir%"  
)
Durch Zeile 6 wird der Text "Geben Sie den Benutzernamen ein: " angezeigt und dann auf eine Eingabe gewartet, die mit ENTER abgeschlossen werden muss. Wenn z.B. "Paul" eingegeben wurde (und nicht nur ENTER gedrückt wurde), würde man erwarten, dass der Inhalt des Verzeichnisses C:\Users\Paul angezeigt wird. Stattdessen erscheint aber der Inhalt des Verzeichnisses, das bei Start des obigen Batchfiles das aktuelle Verzeichnis war.

Warum ist das so? Die Zeilen 8 bis 11 werden vom Befehlsinterpreter als eine Zeile betrachtet. Bevor die Befehle ausgeführt werden, werden alle Variablen durch ihren aktuellen Wert ersetzt (erweitert). Da op_dir zu diesem Zeitpunkt nicht definiert ist, wird Zeile 8 als
dir ""
übersetzt, was einem einfachen DIR entspricht.

Um zum gewünschten Ergebnis zu kommen, muss die verzögerte Variablenerweiterung aktiviert und benutzt werden. Das Beispiel muss dann so lauten:
setlocal enabledelayedexpansion

set "users=C:\Users"  

set "home="  
set /p "home=Geben Sie den Benutzernamen ein: "  

if not "%home%"=="" (  
  set "op_dir=%users%\%home%"  
  dir "!op_dir!"  
)
In Zeile 1 wird durch ENABLEDELAYEDEXPANSION die verzögerte Variablenerweiterung aktiviert. Dadurch, dass in Zeile 10 der Variablenname op_dir in Ausrufezeichen statt in Prozentzeichen eingeschlossen ist, wird dem Befehlsinterpreter mitgeteilt, diesen Variablennamen erst bei Ausführung des DIR-Befehls durch seinen Wert zu ersetzen, der durch den vorhergehenden SET-Befehl gesetzt wurde.


back-to-topWerte von Parametern der FOR-Schleife durch Variablen angeben
Beim Verschachteln von FOR-Schleifen ist folgendes zu beachten:

Die Variante FOR /R hat einen Parameter Basisverzeichnis und die Variante FOR /F hat die Parameter SKIP=x, TOKENS=x, DELIMS=x und EOL=x. Die Werte all diese Parameter können nicht durch eine Laufvariable einer umgebenden FOR-Schleife oder durch eine verzögert erweiterte Variable (in Ausrufezeichen eingeschlossen) angegeben werden. Lediglich die Angabe als normale Umgebungsvariable (in Prozentzeichen eingeschlossen) ist möglich. Verschachtelte FOR-Schleifen werden, wie schon erwähnt, vom Kommandozeileninterpreter als eine Zeile aufgefasst. Wenn solch eine Zeile übersetzt wird, muss der Wert der Variablen, die als Wert einer der o.g. Parameter angegeben ist, schon feststehen und kann sich während der Abarbeitung der Schleifen auch nicht mehr ändern. Diese Voraussetzungen werden nur von normalen Umgebungsvariablen erfüllt.


back-to-topDie Urform der FOR-Schleife

Den FOR-Befehl gab es schon zu DOS-Zeiten, allerdings nur in dieser Form:
FOR %Variable IN (Satz) DO Befehl [Parameter]
Damit lassen sich Zeichenketten und Dateinamensmasken verarbeiten. Satz steht für eine durch Leerzeichen getrennte Folge von Zeichenketten. Enthält eine Zeichenkette selbst Leerzeichen, muss sie in Anführungszeichen eingeschlossen werden. Bei Ausführung der FOR-Schleife wird bei jedem Durchlauf eine der Zeichenketten (angefangen bei der ersten von links) an die Laufvariable zugewiesen. Ist eine Zeichenkette in Anführungszeichen eingeschlossen, werden diese auch an die Laufvariable zugewiesen. Enthält eine Zeichenkette Wildcardzeichen (? oder *), wird sie als Maske für Dateinamen aufgefasst und im angegebenen Verzeichnis oder, ohne Verzeichnisangabe, im aktuellen Verzeichnis nach Dateien gesucht, auf deren Name diese Maske passt. Danach wird pro Schleifendurchlauf in alphabetischer Reihenfolge einer dieser Dateinamen an die Laufvariable zugewiesen.

Beispiel 1 (für die Kommandozeile):
for %i in ("Hallo Welt" "*.txt" Hallo Welt "E:\My Scripts\*.bat") do @echo %i
Wenn sich im aktuellen Verzeichnis die Dateien Test.txt und MeinText.txt befinden und im Verzeichnis E:\My Scripts die Dateien Backup.bat und RDir.bat, ist die Ausgabe folgende:
"Hallo Welt"
Test.txt
MeinText.txt
Hallo
Welt
E:\My Scripts\Backup.bat
E:\My Scripts\RDir.bat
Wurde in Satz zusammen mit einer Dateimaske ein Pfad angegeben, wird er bei der Ausgabe auch angezeigt. Das ist auch der Vorteil gegenüber dem Befehl
dir /b "E:\My Scripts\*.bat"
Die Anführungszeichen um Dateimasken werden nicht ausgegeben. Zeichenketten und Dateimasken lassen sich gemischt angeben.

Beispiel 2:
@echo off & setlocal

cls

set "Dest=E:\Test"  

set /p "FileName=Geben Sie einen Dateinamen ein: "  
if "%FileName%" equ "" goto :EOF  

:SelectAction
  set /p "Action=Möchten Sie diese Datei kopieren oder verschieben (A für Abbruch) (K/V/A)? "  
  for %%i in (K V A) do if /i "%Action%" equ "%%i" goto :%%i  
goto :SelectAction

:K
copy "%FileName%" "%Dest%"  
goto :EOF

:V
move "%FileName%" "%Dest%"  
goto :EOF

:A
endlocal
Hier wird die FOR-Schleife benutzt, um zu prüfen, ob die Variable %Action% einen der zur Eingabe zugelassenen Buchstaben enthält. Durch den Parameter /i beim IF-Befehl sind auch die entsprechenden Kleinbuchstaben zugelassen. Je nach Inhalt von %Action% wird entweder eines der entsprechenden Labels angesprungen oder bei einer unzulässigen Eingabe die Abfrage wiederholt (GOTO :SelectAction). Die GOTO :EOF Befehle springen jeweils zum Programmende (EOF=End Of File), beenden also das Skript.


back-to-topDer Parameter /D
Bei Angabe des Parameters /D wird bei einer Zeichenkette mit Wildcards nur nach Verzeichnissen gesucht, auf deren Name die angegebene Maske passt. Wird die Maske inkl. Pfad angegeben, wird den Namen der gefundenen Verzeichnisse der Pfad vorangestellt und der Laufvariablen zugewiesen.

Beispiel 3 (für die Kommandozeile):
for /d %i in ("E:\My *") do @echo %i
Wenn sich im Verzeichnis E:\ die Verzeichnisse My Scripts und My Docs befinden, ist die Ausgabe folgende:
E:\My Scripts
E:\My Docs


back-to-topDer Parameter /R
Bei Angabe des Parameters /R wird die FOR-Schleife ausgehend vom Verzeichnis [Laufwerk:]Pfad rekursiv für jedes darunter liegende Verzeichnis ausgeführt. Wenn kein Basis-Verzeichnis angegeben wird, wird das aktuelle Verzeichnis verwendet. Für [Laufwerk:]Pfad kann keine Laufvariable einer anderen FOR-Schleife oder eine verzögert erweiterte Variable (in Anführungszeichen eingeschlossen) angegeben werden! Satz ist eine Folge von Zeichenketten, die, wenn sie Wildcards (* oder ?) enthalten, als Maske für Dateinamen interpretiert werden. Alle gefundenen Dateien aus den durchsuchten Verzeichnissen werden inkl. Pfad nacheinander an die Laufvariable zugewiesen. Enthält Satz zusätzlich eine Zeichenkette ohne Wildcards, werden die Pfade aller durchsuchten Verzeichnisse, ergänzt um \Zeichenkette, an die Laufvariable zugewiesen. Ist die Zeichenkette in Anführungszeichen eingeschlossen, wird \"Zeichenkette" ergänzt.

Beispiel 4 (für die Kommandozeile):
for /r "E:\Archiv" %i in ("Audio\*.mp3" Test1 "Test2") do @echo %i
Wenn sich im Verzeichnis E:\Archiv die Dateien Test1.txt und Test2.txt und das Verzeichnis Audio mit den Dateien Test1.mp3, Test2.mp3, Track01.mp3 und Track02.mp3, befinden, ist die Ausgabe folgende:
E:\Archiv\Audio\Test1.mp3
E:\Archiv\Audio\Test2.mp3
E:\Archiv\Audio\Track01.mp3
E:\Archiv\Audio\Track02.mp3
E:\Archiv\Test1
E:\Archiv\"Test2"
E:\Archiv\Audio\Test1
E:\Archiv\Audio\"Test2"

Enthält Satz lediglich einen Punkt, erhält man unter Verwendung der Erweiterung von Laufvariablen einen Ersatz für
dir /s /b /a:d [[Laufwerk:]Pfad]
der auch das Basisverzeichnis liefert. Unter DOS/Windows gibt es nämlich in jedem Verzeichnis zwei Standard-Einträge, die immer vorhanden sind: . und .. Der Punkt (.) stellt einen Verweis auf das Verzeichnis selbst dar. Der zweifache Punkt (..) ist ein Verweis auf das Elternverzeichnis.

Beispiel 5 (für die Kommandozeile):
Auf die eben beschriebene Verzeichnisstruktur angewendet, liefert der Befehl
for /r "E:\Archiv" %i in (.) do @echo %~fi
die folgende Ausgabe:
E:\Archiv
E:\Archiv\Audio

Die Parameter /D und /R können auch kombiniert werden.

Beispiel 6 (für die Kommandozeile):
Wenn auf die schon bekannte Verzeichnisstruktur der Befehl
for /d /r "E:\Archiv" %i in (*) do @echo %i
angewendet wird, ist die Ausgabe folgende:
E:\Archiv\Audio
Das Ergebnis ist also gleichwertig zu
dir /s /b /a:d E:\Archiv


back-to-topDie Variante zur Erzeugung von Zahlenfolgen, FOR /L

FOR /L %Variable IN (Start,Schritt,Ende) DO Befehl [Parameter]
Um mit John Cleese zu sprechen: Kommen wir nun zu etwas völlig anderem. Denn diese Variante der FOR-Schleife verhält sich genauso wie in "richtigen" Programmiersprachen. Die Laufvariable ist eine numerische Größe, die beim Start der Schleife mit dem Wert von Start initialisiert und nach jedem Durchlauf um den Wert von Schritt erhöht wird (negative Schrittweiten sind auch möglich). Die Schleife wird nach dem Durchlauf beendet, in dem die Laufvariable den Wert von Ende erreicht hat.

Beispiel 7:
Das folgende Batchfile, auf die schon bekannte Verzeichnisstruktur E:\Archiv\Audio angewendet,
@echo off

setlocal enabledelayedexpansion

cls

set "cntr=0"  

for %%i in ("E:\Archiv\Audio\*.*") do (  
  set /a "cntr+=1"  
  set "file!cntr!=%%i"  
)

for /l %%i in (1,1,%cntr%) do set file%%i
liefert folgende Ausgabe:
file1=E:\Archiv\Audio\Test1.mp3
file2=E:\Archiv\Audio\Test2.mp3
file3=E:\Archiv\Audio\Track01.mp3
file4=E:\Archiv\Audio\Track02.mp3
Hier wird die verzögerte Variablenerweiterung benutzt, da sich der Inhalt der Variablen %cntr% in der ersten FOR-Schleife bei jedem Durchlauf um 1 erhöhen soll. Je nach Anzahl der gefundenen Dateien werden die Variablen file1 bis fileN erzeugt, die in der zweiten FOR-Schleife mit SET ausgegeben werden.


back-to-topDie Mehrzweck-Variante, FOR /F

FOR /F ["Optionen"] %Variable IN (Ausdruck) DO Befehl [Parameter]
So, kommen wir jetzt zu der Variante, wegen der sicherlich die meisten überhaupt ein Tutorial für die FOR-Schleife benötigen, denn FOR /F ist eine Eierlegende Wollmilchsau. Und wie das so ist mit Werkzeugen, die man für viele Zwecke einsetzen kann, sind sie nicht mal eben so mit links zu benutzen. Hinzu kommt, dass die Auswertung von Ausdruck etwas buggy ist und die Hilfe von FOR zu dieser Variante mehr Verwirrung stiftet als hilfreich zu sein und einige Details verschweigt.


back-to-topAllgemeines zu FOR /F
FOR /F hat drei Untervarianten. Welche verwendet wird, hängt vom Aufbau von Ausdruck und dem Vorhandensein der Option USEBACKQ ab. Man kann

  • eine Zeichenkette verarbeiten.
  • den Inhalt von mehreren explizit angegebenen Dateien (keine Verwendung von Wildcards) zeilenweise verarbeiten.
  • die Ausgabe eines Programms/Befehls zeilenweise verarbeiten.


back-to-topTrennzeichen (Option DELIMS=)
Allen drei Untervarianten ist gemeinsam, dass sie die zu verarbeitenden Zeichenketten/(Datei-)Zeilen in sog. Tokens zerlegen. Ein Token ist ein Teilabschnitt des Gesamtstrings. Wo ein Token beginnt und endet wird durch Trennzeichen (Delimiter) bestimmt. Die Standard-Trennzeichen sind Leerzeichen und Tabzeichen. Man kann aber auch über die Option DELIMS= eigene Trennzeichen definieren oder die Verwendung von Trennzeichen komplett abschalten. Das Anführungszeichen " als Trennzeichen zu definieren ist nicht möglich. Gerüchteweise soll es unter fluchen möglich sein face-wink (Hallo @Biber!). Wer weiss, wie's geht, möge das bitte posten. [EDIT] @pieh-ejdsch hat inzwischen hier veröffentlicht, wie es geht. [/EDIT]


back-to-topZeilenendezeichen (Option EOL=)
Der Zeilenumbruch zählt natürlich auch als Trennzeichen zwischen Tokens und markiert das Zeilenende. Man kann aber über die Option EOL= auch ein eigenes Zeilenendezeichen definieren (EOL=End Of Line). Alle Zeichenketten/(Datei-)Zeilen, die mit dem so definierten Zeichen beginnen, werden komplett ignoriert. Wenn man ein Skript schreiben will, das Konfigurationsdateien auswertet, kann man über EOL=: z.B. den Doppelpunkt als Kommentarzeichen definieren. Zeilen, die damit beginnen, werden dann nicht ausgewertet. Standardmäßig ist das Semikolon (;) das EOL-Zeichen. [EDIT] @jeb-the-batcher stellt in diesem Kommentar noch einen Trick in Zusammenhang mit EOL= zur Verfügung. [/EDIT]


back-to-topZeilen überspringen (Option SKIP=)
Mit der Option SKIP= kann eine Anzahl Zeilen angegeben werden, die vom Anfang einer Datei/Befehlsausgabe übersprungen werden sollen. Diese Zeilen werden nicht verarbeitet. Die Angabe von SKIP=0 ist nicht möglich.


back-to-topTokens (Option TOKENS=)
Die durch die Zerlegung entstehenden Tokens werden der Laufvariablen zugewiesen. Standardmäßig wird immer nur das erste erhaltene Token zugewiesen. Dieses Verhalten kann jedoch über die Option TOKENS= verändert werden. Die Option erwartet eine durch Komma getrennte Aufzählung der zu verwendenden Token-Nummern, z.B. TOKENS=1,3,4,5. Die Angabe von Bereichen ist auch möglich, z.B. TOKENS=1,3-5. Die Angabe von TOKENS=0 ist nicht möglich. Die höchst mögliche Tokennummer ist 31.

Wenn auf diese Art festgelegt wurde, dass mehrere Tokens (Teilabschnitte) einer Zeichenkette/(Datei-)Zeile verarbeitet werden sollen, entsteht automatisch für jedes Token eine zusätzliche Laufvariable. Deren Namen hängen vom Namen der vom Programmierer festgelegten Laufvariablen ab, sie werden in aufsteigender Reihenfolge nach den im Alphabet folgenden Buchstaben benannt. Zur Verdeutlichung ein Beispiel:

Beispiel 8 (für die Kommandozeile):
for /f "skip=5 tokens=1,4" %f in ('dir /a:-d E:\Test') do @echo %g vom %f
Das ist die Untervariante zur Verarbeitung der Ausgabe von Programmen/Befehlen. Zunächst wird der DIR-Befehl in der Klammer ausgeführt, der durch die Option /a:-d keine Unterverzeichnisse listet. So ein Verzeichnislisting sieht z.B. so aus:
 Datenträger in Laufwerk E: ist DATA                                         
 Volumeseriennummer: 1212-3434                                                  
                                                                                
 Verzeichnis von E:\Test                   
                                                                                
08.10.2010  13:16             1.620 Test.txt                              
05.08.2010  15:38               315 Mein Text.txt                             
30.10.2009  18:52             8.519 Anleitung.txt                                    
               3 Datei(en)         10.454 Bytes                                 
               0 Verzeichnis(se), 36.387.303.424 Bytes frei                     
Die ersten 5 Zeilen dieser Ausgabe interessieren uns nicht, deshalb SKIP=5.

In den nun folgenden 3 Zeilen mit den Dateien ist das erste Token das Erstellungsdatum, denn nach dem Datum folgen Leerzeichen, die zu den Standardtrennzeichen gehören. Da in der Befehlszeile TOKENS=1,4 steht, wird der Laufvariablen %f (von mir festgelegt) das Dateidatum zugewiesen.

Das zweite Token ist die Uhrzeit der Dateierstellung, das dritte Token die Dateigröße. Diese beiden Tokens werden ignoriert.

Das vierte Token ist der Dateiname mit Erweiterung. Da dieses Token laut Befehlszeile verarbeitet werden soll, wird automatisch eine weitere Laufvariable %g (g folgt im Alphabet auf f) erzeugt und bekommt den Dateinamen zugewiesen.

Außer bei der Datei mit dem Namen "Mein Text.txt". Dieser Name enthält ein Leerzeichen, also ein Trennzeichen. Deshalb enthält %g nur "Mein". Wie kommt man an den Rest des Dateinamens? Der Code muss folgendermaßen geändert werden:

Beispiel 9 (für die Kommandozeile):
for /f "skip=5 tokens=1,4,*" %f in ('dir E:\Test /a:-d') do @(if "%h" equ "" (echo %g vom %f) else (echo %g %h vom %f))
Endet die Liste der zu verwendenden Tokens mit einem Stern (*), wird automatisch eine weitere Laufvariable erzeugt, die alle Tokens inkl. Trennzeichen nach dem zuletzt genannten Token (hier dem 4.) enthält. Token 1 steht in %f (von mir festgelegt), Token 4 steht in %g (automatisch erzeugt). Der Rest der Ausgabezeile steht also in %h (auch automatisch erzeugt). Wenn %h nichts enthält, enthält der Dateiname kein Leerzeichen und es genügt, echo %g vom %f auszuführen. Wenn %h jedoch einen Inhalt hat, muss echo %g %h vom %f ausgeführt werden; zwischen %g und %h muss das als Trennzeichen "verschluckte" Leerzeichen von Hand wieder eingefügt werden.

Sinnvoll ist die Ausgabe des Beispielcodes aber dennoch nicht:
Test.txt vom 08.10.2010
Mein Text.txt vom 05.08.2010
Anleitung.txt vom 30.10.2009
Bytes vom 3
Bytes frei vom 0
Die letzten beiden Zeilen sind Unsinn. Hier tritt eine Schwäche von FOR /F zu Tage: Es gibt zwar die Möglichkeit (mit SKIP=) eine bestimmte Anzahl Zeilen vom Anfang der zu verarbeitenden Datei/Befehlsausgabe zu überspringen, aber keine Möglichkeit, eine bestimmte Anzahl Zeilen am Ende zu ignorieren oder nur eine bestimmte Anzahl Zeilen zu verarbeiten. Für das in diesem Beispiel behandelte Problem existiert aber trotzdem eine Lösung, die ich im Abschnitt Erweiterung von Laufvariablen vorstellen werde.

Wenn man tatsächlich einmal in die Lage kommt, 31 Tokens verarbeiten zu müssen, stellt sich die Frage nach dem Namensraum der dann nötigen Laufvariablen. Meine Versuche haben ergeben, dass man in diesem Fall der selbst benannten Laufvariablen am besten den Namen %? gibt. Es entstehen dann die automatischen Laufvariablen %@, %A, ..., %Z, %[, %\ und %]. Das ergibt einen zusammenhängenden Namensraum von 31 Variablen, die sich ohne Probleme benutzen lassen. Problemkinder im 7Bit-ASCII-Codebereich sind z.B. %,<,> und ^. Ausserdem ist es ungeschickt, die Ziffern 0 bis 9 in den Namensraum aufzunehmen, da man dann die Möglichkeit verliert, auf die Variablen %0 ... %9, die die Parameter des Batchfiles/des Unterprogramms repräsentieren, Bezug zu nehmen. Im erweiterten 8Bit-ASCII-Codebereich jenseits von Zeichen 127 gibt es auch immer wieder einzelne Zeichen oder kleine Blöcke von Zeichen, die sich nicht als Variablennamen verwenden lassen.


back-to-topDie Auswertung von Ausdruck beeinflussen (Option USEBACKQ)
Die Option USEBACKQ kann nur im Kontext der verschiedenen Untervarianten von FOR /F erklärt werden. Ich verweise deshalb auf die entsprechenden Abschnitte.


back-to-topVerarbeiten einer Zeichenkette
Die Syntax zum Verarbeiten einer Zeichenkette ist:
FOR /F ["Optionen"] %Variable IN ("Zeichenkette") DO Befehl [Parameter]
oder bei Verwendung der Option USEBACKQ
FOR /F "usebackq[ Optionen]" %Variable IN ('Zeichenkette') DO Befehl [Parameter]
Die Zeichenkette wird als eine Zeile einer Datei aufgefasst und entsprechend der Optionen DELIMS=, TOKENS= und EOL= zerlegt. Die Zeichenkette kann bei der Version ohne die Option USEBACKQ auch selbst Anführungszeichen enthalten, bei der Version mit USEBACKQ sollten jedoch keine Apostrophe in der Zeichenkette enthalten sein. Bei meinen Tests kam es in diesem Fall bei direkter Eingabe des Befehls an der Kommandozeile nach einem Verzeichniswechsel zu Fehlfunktionen von CMD.EXE. Die umgebenden Anführungszeichen werden nicht an die Laufvariable(n) zugewiesen. Bei Angabe von mehreren Zeichenketten kommt es auch zu Fehlfunktionen von CMD.EXE.

Beispiel 10:
In Batch-Skript kann mit dem Befehl SET /A gerechnet werden. Zahlen, die führende Nullen enthalten, werden dabei als Zahlen im Oktalsystem (zur Basis 8) interpretiert. Das führt beim Verrechnen von 08, 09, 018, 019 usw. zu Fehlermeldungen (diese Zahlen gibt es im Oktalsystem nicht), bei anderen Zahlen zu falschen Ergebnissen. Deshalb hier ein Schnipsel, der diese führenden Nullen abschneidet.
::Entfernen von führenden Nullen bei Zahlen, damit sie
::in Berechnungen nicht als Oktalzahlen aufgefasst werden

@echo off & setlocal

cls
set /p "Number=Geben Sie eine Zahl mit oder ohne führende Nullen ein: "  

for /f "tokens=* delims=0" %%n in ("%Number%") do set "Number=%%n"  
set /a "Number=Number"  

echo Die eingegebene Zahl ist %Number%
Als Trennzeichen wird durch DELIMS=0 die Ziffer 0 vereinbart. Durch TOKENS=* enthält die Laufvariable alle Tokens inkl. der vereinbarten Trennzeichen. Das erste Token beginnt aber erst dann, wenn ein vom Trennzeichen verschiedenes Zeichen auftritt, also bei der ersten von 0 verschiedenen Ziffer. Deshalb werden die führenden Nullen abgeschnitten, später auftretende Nullen bleiben erhalten. Zeile 10 dient nur dazu, die Variable %Number% auf 0 zu setzen, wenn 0 oder z.B. 0000 eingegeben oder einfach nur ENTER gedrückt wurde.

Ein Manko hat der Code: Man muss Zahlen eingeben, die Eingabe von Buchstaben wird nicht verhindert (Hallo Timo!). Im Abschnitt Praxistipps habe ich einen Schnipsel notiert, der das abfängt. Ihn hier zu verwenden wäre verfrüht, ich würde im Tutorial vorgreifen.

Beispiel 11:
Mit FOR /F und Zeichenketten lassen sich Arrays simulieren. Die Option TOKENS= kann dazu benutzt werden, um den Index des Elements im Array anzugeben, auf das zugegriffen werden soll. Im nachfolgenden Beispiel wird das Standard-Trennzeichen SPACE (Leerzeichen) verwendet, um die "Arrayelemente" zu separieren. Sollen die Arrayelemente selbst Leerzeichen enthalten, kann mit DELIMS=, z.B. das Komma als Trennzeichen vereinbart werden.
::Hex=>Dec Konverter mit Array-Simulation

@echo off & setlocal

set "HexDigits=0 1 2 3 4 5 6 7 8 9 A B C D E F"  
set "ConvArray=0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15"  
set "Result=0"  

cls
set /p "HexNum=Geben Sie eine hexadezimale Zahl ein (max. 8-stellig): "  

:ConvLoop
  set "Digit=%HexNum:~0,1%"  
  set "HexNum=%HexNum:~1%"  

  set "Index=1"  

  :ArrayLookup
    for /f "tokens=%Index%" %%i in ("%HexDigits%") do (  
      if /i "%Digit%" equ "%%i" (  
        for /f "tokens=%Index%" %%j in ("%ConvArray%") do (  
          set "DecValue=%%j"  
          goto :CalcResult
        )
      )
    )

    set /a "Index+=1"  
  if %Index% leq 16 (goto :ArrayLookup) else (goto :ForbiddenChar)

  :CalcResult
  set /a "Result=Result*16+DecValue"  
if "%HexNum%" neq "" goto :ConvLoop  

echo Das dezimale Äquivalent dieser Zahl ist %Result%
exit /b

:ForbiddenChar
echo Es sind nur die Zeichen 0-9, a-f und A-F zur Eingabe erlaubt.
exit /b
In Zeile 13 wird die erste Hex-Ziffer von links (ab dem Offset 0, 1 Zeichen) der Variablen %DIGIT% zugewiesen. In Zeile 14 wird diese Ziffer von der Variablen %HexNum% abgeschnitten (%HexNum% ist gleich Inhalt von %HexNum% ab dem Offset 1 bis zum Ende). Wenn %HexNum% leer ist, wird die Hauptschleife in Zeile 33 beendet.

Die Zeilen 18 bis 28 suchen im Array %HexDigits% nach der aktuell betrachteten Hex-Ziffer %Digit%. Wird sie gefunden, wird am gleichen Index in %ConvArray% das dezimale Äquivalent ausgelesen und die Schleife abgebrochen. Wenn die Schleife bis zum Ende (%Index% gleich 17) durchläuft, bedeutet das, dass ein Zeichen eingegeben wurde, was keine Hex-Ziffer darstellt und das Skript wird mit einer Fehlermeldung abgebrochen.

Man könnte einwenden, die Zeilen 18 bis 28 könnte man doch als FOR /L Schleife programmieren, also den Index damit erzeugen lassen. Hier kommt aber eine Einschränkung von FOR /F zum tragen: Die Werte bei TOKENS=, SKIP=, EOL= und DELIMS= dürfen keine Laufvariable einer anderen FOR-Schleife oder eine verzögert erweiterte Variable (in Ausrufezeichen eingeschlossen) enthalten. Der Grund dafür dürfte in der Art und Weise liegen, wie der Befehlszeileninterpreter eine solche Zeile auswertet und übersetzt.

Übrigens: Der einfachste Hex=>Dec Konverter in Batchskript ist natürlich
set /a "DecNum=0x%HexNum%"


back-to-topVerarbeiten des Inhalts von Dateien
Die Syntax zum Verarbeiten des Inhalts von Dateien ist:
FOR /F ["Optionen"] %Variable IN (Dateiname[ ...]]) DO Befehl [Parameter]
oder bei Verwendung der Option USEBACKQ
FOR /F "usebackq[ Optionen]" %Variable IN ("Dateiname"[ ...]]) DO Befehl [Parameter]
Die Angabe von mehreren Dateien ist möglich. Die Dateien werden zeilenweise ausgelesen. Jede einzelne Zeile wird entsprechend den Optionen DELIMS=, TOKENS=, EOL= und SKIP= verarbeitet. Die bei der Zerlegung der einzelnen Dateizeilen entstehenden Tokens werden der/den Laufvariablen zugewiesen. Leere Zeilen werden nicht an die Laufvariable(n) zugewiesen. Wie das dennoch geht zeigt Beispiel 7a im Abschnitt Praxistipps.

Bei der Version mit USEBACKQ kann der Dateiname oder -pfad Leerzeichen enthalten, ohne USEBACKQ ist das nicht möglich. Gerade wenn man mit Dateinamen arbeitet, die während des Skriptlaufs dynamisch erzeugt werden, ist es deshalb fast schon Pflicht mit der USEBACKQ-Version zu arbeiten.

Beispiel 12:
::Konfigurationsdatei einlesen
::und dadurch Skript-Variablen setzen

@echo off & setlocal

set "ConfigFile=C:\Programme\Backup\Backup.conf"  

set "VarMissed=0"  
set "Vars=Source Destination ExcludeFiles ExcludeDirs"  

for %%v in (%Vars%) do set "%%v="  

for /f "usebackq tokens=1,2 delims==" %%v in ("%ConfigFile%") do set "%%v=%%w"  

for %%v in (%Vars%) do (
  if not defined %%v (
    call :MissingVar %%v
    set "VarMissed=1"  
  )
)

if %VarMissed% equ 1 goto :ScriptEnd
.
.
.
:ScriptEnd
endlocal
exit /b


:MissingVar
  echo Variable %1 ist in der Konfigurationsdatei nicht definiert.
exit /b
Die erste FOR-Schleife in Zeile 11 löscht die Variablen, deren Namen in der Variablen %Vars% angegeben sind.

Die FOR /F Schleife in Zeile 13 liest die Datei, deren Name in der Variablen %ConfigFile% gespeichert ist, ein. Als Trennzeichen zwischen den Tokens wird das Gleichheitszeichen definiert. Die Laufvariable %%v enthält deshalb den Namen der Variablen, die durch TOKENS=1,2 automatisch definierte Laufvariable %%w enthält alles, was rechts vom Gleichheitszeichen in der Konfigurationsdatei steht. Durch das standardmäßig als Zeilenendezeichen definierte Semikolon können Kommentarzeilen in die Konfigurationsdatei geschrieben werden, die mit einem Semikolon beginnen.

Die dritte FOR-Schleife in Zeile 15-20 prüft, ob alle Variablen, deren Namen in der Variablen %Vars% angegeben sind, definiert sind. Wenn eine nicht definierte Variable gefunden wird, wird das Unterprogramm MissingVar mit dem Namen der nicht definierten Variablen als Parameter aufgerufen und eine Fehlermeldung ausgegeben. Außerdem wird die Variable %VarMissed% auf den Wert 1 gesetzt.

Wenn in Zeile 22 festgestellt wird, dass %VarMissed% den Wert 1 hat, wird das Skript abgebrochen.

Wenn die Datei Backup.conf folgenden Aufbau hat,
;Datenquelle
Source=D:\Daten

;Backup-Ziel
Destination=P:\Backup

;Dateitypen, die nicht kopiert werden sollen
ExcludeFiles=*.bak,*.tmp

;Verzeichnisse, die nicht kopiert werden sollen
ExcludeDirs=\Test,\Skript\Versuch
sind nach Ausführung von Zeile 13 in obigem Skript die Variablen Source, Destination, ExcludeFiles und ExcludeDirs mit den angegebenen Werten belegt.


back-to-topVerarbeiten der Ausgabe eines Programms/Befehls
Die Syntax zum Verarbeiten der Ausgabe eines Programms/Befehls ist:
FOR /F ["Optionen"] %Variable IN ('Befehl1 [Parameter]') DO Befehl2 [Parameter]
oder bei Verwendung der Option USEBACKQ
FOR /F "usebackq[ Optionen]" %Variable IN (`Befehl1 [Parameter]`) DO Befehl2 [Parameter]
Im Unterschied zur Version ohne USEBACKQ wird der auszuführende Befehl bei der Version mit USEBACKQ in Gravis-Zeichen (SHIFT+Taste neben BACKSPACE, danach SPACE (Leerzeichen) drücken) eingeschlossen.

Befehl1 wird in einer separaten, versteckten Instanz von CMD.EXE ausgeführt. Die Ausgabe erscheint nicht auf dem Bildschirm, sondern wird zeilenweise unter Beachtung der Optionen DELIMS=, TOKENS=, EOL= und SKIP= verarbeitet. Die bei der Zerlegung der einzelnen Ausgabezeilen entstehenden Tokens werden der/den Laufvariablen zugewiesen. Leere Ausgabezeilen werden nicht an die Laufvariable(n) zugewiesen. Wie das dennoch geht zeigt Beispiel 7b im Abschnitt Praxistipps.

Wenn Befehl1 ein Programm ist, dessen Pfad Leerzeichen enthält, muss Befehl1 in Anführungszeichen eingeschlossen werden. Falls Befehl1 zusätzlich einen Parameter benötigt, der Leerzeichen enthält und deshalb ebenfalls in Anführungszeichen eingeschlossen werden muss (z.B. einen Dateipfad), funktioniert FOR /F nur unter Verwendung folgender Syntax:
FOR /F ["Optionen"] %Variable IN ('call "Befehl1" "Parameter"') DO Befehl2 [Parameter]
oder bei Verwendung der Option USEBACKQ
FOR /F "usebackq[ Optionen]" %Variable IN (`call "Befehl1" "Parameter"`) DO Befehl2 [Parameter]


back-to-topEscapen von Steuerzeichen
Wenn Befehl1 bestimmte Zeichen/Zeichenkombinationen enthält, müssen diese unter Verwendung des Zeichens ^ "escaped" werden, d.h. das Escapezeichen ^ muss ihnen vorangestellt werden um zu verdeutlichen, dass das nachfolgende Zeichen nicht als Steuerzeichen interpretiert, sondern genau so an die Befehl1 ausführende Instanz von CMD.EXE übergeben werden soll. Die folgende Tabelle gibt einen Überblick.

[Edit] Neue Erkenntnisse zum Thema hat @pieh-ejdsch in diesem Posting veröffentlicht. [/Edit]

Zeichen Bedeutung "escapen" mit
> Ausgabeumleitung (in Datei) ^>
< Eingabeumleitung (aus Datei) ^<
2>&1 Standardfehlerkanal (Kanal 2) dorthin umleiten,
wohin auch die Standardausgabe (Kanal 1 ) umgeleitet ist
2^>^&1
| Ausgabeumleitung eines Befehls in eine Pipe ^|
& Befehlsverkettung ^&
&& Bedingte Befehlsverkettung
Bei Erfolg des vorhergehenden Befehls
^&^&
| | Bedingte Befehlsverkettung
Bei Misserfolg des vorhergehenden Befehls
^|^|
( öffnende Klammer ^(
) schließende Klammer ^)
= Zuweisungen ^=
, Komma ^,
^ das Escapezeichen selbst ^^


Beispiel 13:
::Bestimmen der Länge einer Zeichenkette

@echo off & setlocal

set /p "Str=Geben Sie einen String ein: "  

set "StrLen=0"  

>"%TEMP%\strlen.txt" (echo ^<%Str%&echo ^<)  
for /f "delims=:" %%l in ('findstr /o /b "<" "%TEMP%\strlen.txt"') do set /a "StrLen=%%l-3"  

del "%TEMP%\strlen.txt"  

echo Die Länge von %Str% ist %StrLen%
In Zeile 5 wird der Benutzer zur Eingabe einer Zeichenkette aufgefordert, die der Variablen %Str% zugewiesen wird. In Zeile 9 wird diese Zeichenkette zusammen mit Steuerzeichen in die Datei strlen.txt ins Verzeichnis für temporäre Dateien %TEMP% (vordefinierte Umgebungsvariable) geschrieben. Da das Zeichen < zum Sprachumfang von Batchskript gehört (Steuerzeichen für Eingabeumleitung), muss es mit dem Zeichen ^ "escaped" werden. Der Inhalt von strlen.txt sieht nach Eingabe von z.B. Ein String folgendermaßen aus:
<Ein String
<
Der FINDSTR-Befehl in der Klammer der FOR-Schleife in Zeile 10 durchsucht die Datei strlen.txt wegen dem Parameter /b nach Zeilen, die mit < beginnen und gibt diese aus. Vor dem Zeileninhalt wird wegen dem Parameter /o der Offset des ersten Zeichens der Zeile relativ zum Dateianfang, gefolgt von einem Doppelpunkt, ausgegeben. Die Ausgabe sieht für das Beispiel also so aus:
0:<Ein String
13:<
Diese Ausgabe wird ja bekanntlich nicht angezeigt, sondern durch die FOR-Schleife verarbeitet. Als Trennzeichen zwischen Tokens ist durch DELIMS=: der Doppelpunkt definiert. Weil die Angabe Tokens=X fehlt, wird nur das erste Token jeder Zeile verarbeitet. Da strlen.txt zwei Zeilen enthält, wird die FOR-Schleife zweimal durchlaufen. Beim zweiten Durchlauf hat die Laufvariable %%l also den Wert 13. Dieser Wert kommt folgendermaßen zustande: Das Zeichen <, nach dem FINDSTR sucht, am Anfang der ersten Zeile von strlen.txt hat den Offset 0. Deshalb gibt FINDSTR in seiner Ausgabe 0: vor der ersten Zeile aus. Das Zeichen g des Wortes String hat den Offset 10. Danach kommen in der Datei noch die zwei Zeichen <CARRIAGE RETURN> (Wagenrücklauf, ASCII-Code 13) und <LINEFEED> (Zeilenvorschub, ASCII-Code 10). Diese werden von FINDSTR mitgezählt. Deshalb hat das erste Zeichen < der zweiten Zeile von strlen.txt den Offset 13 relativ zum Dateianfang. Von diesem Offset muss man den Wagenrücklauf, den Zeilenvorschub und das Zeichen < in der ersten Zeile von strlen.txt (also 3) subtrahieren und erhält somit die Länge der Zeichenkette in Zeile 1 von strlen.txt.

Übrigens: Der Suchstring des FINDSTR-Befehls, das Zeichen <, muss nicht "escaped" werden, da er von Anführungszeichen eingeschlossen ist.


back-to-topErweiterung von Laufvariablen

Der Inhalt von Laufvariablen der FOR-Schleife kann durch hinzufügen bestimmter Kürzel zum Variablennamen verändert dargestellt werden. Fast alle Funktionen beziehen sich auf den Fall, dass die Laufvariable einen Dateinamen/-pfad enthält. In der folgenden Tabelle wird angenommen, dass die Laufvariable %I ist. Die gleichen Möglichkeiten zur Manipulation hat man auch bei den Variablen %0, %1, ... , %9, die die einem Batchfile/Unterprogramm übergebenen Parameter repräsentieren. Die Beschreibung habe ich weitgehend aus der FOR-Hilfe übernommen.

%~I Erweitert %I und entfernt alle umschließenden Anführungszeichen (").
%~fI Erweitert %I zu einem vollständigen Dateinamen inkl. Laufwerksbuchstaben und Pfad.
%~dI Erzeugt nur den Laufwerksbuchstaben von %I.
%~pI Erzeugt nur den Pfad von %I ohne Laufwerksbuchstaben.
%~nI Erzeugt nur den Dateinamen von %I.
%~xI Erzeugt nur die Dateierweiterung von %I.
%~sI Erweitert %I zu einem vollständigen Dateinamen, in dem nur kurze Datei-/Verzeichnisnamen im 8.3-Format vorkommen.
%~aI Erzeugt die Dateiattribute von %I.
%~tI Erzeugt Datum und Zeit von %I.
%~zI Erzeugt die Dateigröße von %I.
%~$PATH:I Durchsucht die in der PATH-Umgebungsvariablen angegebenen Verzeichnisse nach der Datei, deren Name in %I steht und erweitert den Ausdruck auf Laufwerksbuchstabe:\Pfad\Dateiname.Erweiterung der ersten gefundenen Datei. Statt PATH kann auch eine andere Umgebungsvariable angegeben werden. Wenn der Name der Umgebungsvariablen nicht definiert ist oder die Datei, deren Name in %I steht, bei der Suche nicht gefunden wurde, wird der Ausdruck zu einer leeren Zeichenkette erweitert.


Beispiel 14 (für die Kommandozeile):
Betrachten wir ein Verzeichnis, bei dem DIR E:\Test\*.txt die folgende Ausgabe liefert:
 Datenträger in Laufwerk E: ist DATA
 Volumeseriennummer: 1212-3434

 Verzeichnis von E:\Test

30.10.2010  18:52             8.519 Doku-Test.txt
09.09.2009  22:21               298 Versuch.txt
               2 Datei(en)         8.817 Bytes
               0 Verzeichnis(se), 36.579.278.848 Bytes frei

Die folgende Tabelle gibt an, wie die Ausgabe zu jedem hinzugefügten Kürzel aussieht.

Befehl Ausgabe
for /f "delims=" %F in ('dir /b E:\Test\*.txt') do @echo %~fF E:\Test\Doku-Test.txt
E:\Test\Versuch.txt
for /f "delims=" %F in ('dir /b E:\Test\*.txt') do @echo %~dF E:
E:
for /f "delims=" %F in ('dir /b E:\Test\*.txt') do @echo %~pF \Test\
\Test\
for /f "delims=" %F in ('dir /b E:\Test\*.txt') do @echo %~nF Doku-Test
Versuch
for /f "delims=" %F in ('dir /b E:\Test\*.txt') do @echo %~xF .txt
.txt
for /f "delims=" %F in ('dir /b E:\Test\*.txt') do @echo %~sF E:\Test\Doku-T~1.txt
E:\Test\Versuch.txt
for /f "delims=" %F in ('dir /b E:\Test\*.txt') do @echo %~aF --a------
--a------
for /f "delims=" %F in ('dir /b E:\Test\*.txt') do @echo %~tF 30.10.2010 18:52
09.09.2009 22:21
for /f "delims=" %F in ('dir /b E:\Test\*.txt') do @echo %~zF 8519
298
for %F in ("cmd.exe") do @echo %~F cmd.exe
for %F in ("cmd.exe") do @echo %~$Path:F C:\WINDOWS\system32\cmd.exe

Achtung! Der Befehl DIR /b E:\Test\*.txt aus den obigen Beispielen gibt nur die Dateinamen ohne Pfad aus. Wenn das aktuell gesetzte Verzeichnis nicht E:\Test ist und auch dort eine Datei mit Namen Versuch.txt vorhanden ist, werden von %~fF, %~dF, %~pF, %~sF, %~aF, %~tF und %~zF Daten zurückgegeben, die sich auf diese Datei beziehen, nicht auf E:\Test\Versuch.txt! Wenn Doku-Test.txt und Versuch.txt im aktuellen Verzeichnis nicht vorhanden sind, wird keine Fehlermeldung erzeugt, die Angaben zu Laufwerksbuchstaben und Pfaden werden einfach vom aktuellen Verzeichnis übernommen. Um obige Operatoren zu verwenden, immer dafür sorgen, dass die Laufvariable vollständige Pfade enthält!

Die o.g. Kürzel/Operatoren können auch kombiniert werden. So liefert z.B. %~dpF bei obigen Beispieldateien
E:\Test\
E:\Test\
und %~dpnxF ist gleichwertig zu %~fF.

Beispiel 15 (für die Kommandozeile):
Mit der Erweiterung von Laufvariablen und zwei geschachtelten FOR-Schleifen lässt sich das Problem aus Beispiel 9 nun lösen.
for %f in ("E:\Test\*.txt") do @(for /f %d in ("%~tf") do @echo %~nf vom %d)
Die äußere FOR-Schleife listet die gewünschten Dateien mit Pfaden. Die innere FOR-Schleife wertet eine Zeichenkette aus, die aus dem Erstellungsdatum und der Erstellungszeit der Dateien besteht. Zwischen diesen beiden Angaben wird durch %~tf ein Leerzeichen erzeugt. Das erste Token ist das Erstellungsdatum, was an die Laufvariable %d zugewiesen wird. Der ECHO-Befehl gibt nur den Dateinamen, ohne Laufwerksbuchstaben und Pfad, sowie das Datum aus.

Wie man sieht, kann in der inneren FOR-Schleife die Laufvariable der äußeren FOR-Schleife benutzt werden.


back-to-topFOR-Schleifen und GOTO

Ein GOTO-Befehl innerhalb von FOR-Schleifen, dessen Sprungziel ein Label ist, das ebenfalls innerhalb der FOR-Schleife liegt, führt zwar zu keiner Fehlermeldung, funktioniert aber nicht wie gewünscht. Ich übernehme hier Beispiele von @jeb-the-batcher aus seinem Kommentar zu diesem Tutorial.

Beispiel 16
FOR-Schleifen brechen ab, sobald man GOTO verwendet, selbst wenn das Ziel innerhalb der Schleife liegt.
@echo off

for /l %%n in (1,1,100) do (
  echo %%n
  goto :label
  :label
  echo %%n
)

echo ende
Die Ausgabe ist folgende:
1
%n
ende
Statt in Zeile 7 den Inhalt der Laufvariablen auszugeben, wird nur noch %n ausgegeben. Von dem doppelten Prozentzeichen wird vom Befehlszeileninterpreter automatisch eines entfernt und das ganze nur noch als Text ausgegeben, weil der Befehl schon nicht mehr im Kontext der FOR-Schleife ausgeführt wird und somit die Laufvariable %%n nicht mehr definiert ist.

Beispiel 17
Aber Abbruch ist hier nicht mit einem sofortigen Abbruch zu verwechseln, hier dauert der Abbruch 10,5 Sekunden (System: Athlon 64 X2 3600+, 2x2GHz).
@echo off

for /l %%n in (1,1,1000000) do (
  echo %%n - %time%
  goto :xx
  :xx
  echo %%n - %time%
)

echo ende
Die Ausgabe ist z.B. folgende:
1 - 16:48:54,93
%n - 16:49:05,43
ende
An den Zeitangaben sieht man, dass die Schleife anscheinend wirklich 1.000.000 mal durchläuft. Die beiden ECHO-Befehle werden trotzdem jeweils nur einmal ausgeführt. Da hier keine verzögerte Variablenerweiterung aktiviert und benutzt wurde, müsste die Variable %time% auch bei beiden Ausgaben den gleichen Wert haben. Da das nicht so ist, sieht man auch daran, dass Zeile 7 ausserhalb des Kontexts der FOR-Schleife ausgeführt wird.


back-to-topPraxistipps

Dieser Abschnitt ist als "Mitmach-Abschnitt" gedacht. Wer will, kann einen Schnipsel mit Erklärung posten, der

  • erstaunlich kurz und trotzdem nützlich ist,
  • besonders raffiniert programmiert ist oder
  • einfach nur ein besonderes Detail von FOR-Schleifen vorstellt.

Ich werde die Postings in diesen Abschnitt integrieren. Mit der letzten Sorte von Schnipseln fange ich hier mal an.


1. Der Code
for %f in (E:\Test\*.*) do @echo %f
ist kürzer und schneller als
for /f "delims=" %f in ('dir /b /a:-d E:\Test') do @echo %f
und liefert vollständige Pfade. Übrigens: Ich habe um den DIR-Befehl einen FOR /F Befehl gelegt, damit das Ergebnis, so wie bei der FOR-Variante, in einer Variablen vorliegt.


2. Der Code
for /r E:\Test %d in (.) do @echo %~fd
liefert ein ähnliches Ergebnis wie
for /f "delims=" %d in ('dir /s /b /a:d E:\Test') do @echo %d
Die FOR /R Variante ist kürzer und schneller und es wird auch das Basisverzeichnis E:\Test gelistet.


3. Auch
for /r E:\Test %d in (..) do @echo %~fd
und
for /f "delims=" %d in ('dir /s /b /a:d E:\Test') do @echo %~dpd
sind sich im Ergebnis ähnlich. Abgesehen davon, dass die FOR /R Variante kürzer und schneller ist, wird auch das Wurzelverzeichnis gelistet und die Pfade haben keinen abschließenden Backslash (außer beim Wurzelverzeichnis E:\).


4. Beispiel 10 in einer Version, die die Eingabe von Zeichen, bei denen es sich nicht um Zahlen handelt, abfängt.
::Entfernen von führenden Nullen bei Zahlen, damit sie
::in Berechnungen nicht als Oktalzahlen aufgefasst werden

@echo off & setlocal

:InputNumber
  cls
  set /p "Number=Geben Sie eine Zahl mit oder ohne führende Nullen ein: "  
for /f %%c in ('echo %Number%^|findstr "[^0-9]"') do goto :InputNumber  

for /f "tokens=* delims=0" %%n in ("%Number%") do set "Number=%%n"  
set /a "Number=Number"  

echo Die eingegebene Zahl ist %Number%
Gegenüber dem Beispiel 10 ist als relevanter Code nur Zeile 9 hinzugekommen. Deshalb werde ich nur dazu etwas sagen. Der Befehl FINDSTR wird hier dazu verwendet, um zu prüfen, ob %Number% etwas anderes als Zahlen enthält. Zuerst wird %Number% mit dem ECHO-Befehl ausgegeben. Die Ausgabe wird über eine Pipe an FINDSTR weitergeleitet. Der Suchstring von FINDSTR ist ein regulärer Ausdruck. Durch [^0-9] wird eine Klasse von Zeichen definiert. Diese Klasse enthält alle Zeichen ausser den Ziffern 0 bis 9. Enthält %Number% etwas anderes als Zahlen, findet FINDSTR also etwas, auf was sein Suchstring zutrifft. Dadurch wird die Ausgabe von FINDSTR an die Laufvariable %%c zugewiesen und der Befehl im Schleifenkörper des FOR-Befehls ausgeführt, also der Rücksprung zum Label InputNumber. Damit das ganze funktioniert, ist es wichtig, dass kein Leerzeichen zwischen dem abschließenden Prozentzeichen von %Number% und dem Escapezeichen ^ vor dem Pipezeichen | steht, das würde vom ECHO-Befehl sonst auch ausgegeben und der Rücksprung somit immer ausgeführt.


5. In Beispiel 12 wird ein Schnipsel vorgestellt, der eine Konfigurationsdatei einließt und dementsprechend Skript-Variablen setzt. Nachteilig an der Sache ist, daß ein Anwender gezwungen wäre, so eine Konfigurationsdatei mit einem Editor zu schreiben, der im DOS-/ASCII-Mode abspeichern kann, sonst gibt es Probleme bei Verzeichnisnamen, die eins der Zeichen ÄÖÜäöüß enthalten, denn die Befehle der Kommandozeile arbeiten immer noch im ASCII-Modus. Es muss also ein ANSI=>ASCII Konverter her, dann kann man Konfigurationsdateien mit Notepad schreiben.

Das folgende Skript demonstriert dabei gleich noch einen Programmiertrick. Oft ist man nämlich gezwungen, die verzögerte Variablenerweiterung zu benutzen, bekommt dann aber Probleme mit Variablen, die zur Laufzeit ein Ausrufezeichen enthalten können (z.B. weil Datei- oder Verzeichnisnamen darin gespeichert werden sollen). Es gibt aber eine Möglichkeit, auf die verzögerte Variablenerweiterung zu verzichten, indem man den Code, der mit einer in der FOR-Schleife veränderten Variablen arbeitet, in ein Unterprogramm auslagert. Netterweise hat die Variable dort, auch wenn ihr Name statt mit Ausrufezeichen ganz normal mit Prozentzeichen eingeschlossen ist, immer ihren aktuellen Wert. Im nachfolgenden Skript wird diese Technik aber nur deshalb verwendet, weil das Hin- und Herschalten der Codepage in der FOR-Schleife nicht funktioniert hat.
::Konfigurationsdatei vom ANSI- ins ASCII-Format konvertieren

set "ConfigFile=C:\Programme\Backup\Backup.conf"  
set "TempConfigFile=%Temp%\Backup.conf"  

::Evtl. vorhandene temporäre Konfigurationsdatei löschen
type NUL > "%TempConfigFile%"  

::ANSI-Codepage aktivieren
chcp 1252 > NUL

::Datei zeilenweise konvertieren
for /f "usebackq delims=" %%l in ("%ConfigFile%") do (  
  set "line=%%l"  
  call :Convert2ASCII
)

::Konfiguration einlesen
for /f "usebackq tokens=1,2 delims==" %%v in ("%TempConfigFile%") do set "%%v=%%w"  

::Temporäre Konfigurationsdatei löschen
del "%TempConfigFile%"  

.
.
.

exit /b


:Convert2ASCII
  ::auf DOS-Codepage umschalten
  chcp 850 > NUL

  ::Eine Zeile schreiben
  >>"%TempConfigFile%" echo %line%  
exit /b


6. Um die Inhalte zweier Dateien zeilenweise zu mischen kann folgender Code verwendet werden:
@echo off
setlocal enabledelayedexpansion

set "InFile1=.\Test1.txt"  
set "InFile2=.\Test2.txt"  
set "OutFile=.\Merged.txt"  

(for /f "tokens=1* delims=:" %%a in ('findstr /n "^" "%InFile1%"') do (  
   set "line="  
   set /p "line="  
   echo.%%b
   echo.!line!
)) <"%InFile2%" >"%OutFile%"  
Bei jedem Schleifendurchlauf wird aus jeder der beiden Eingabedateien jeweils eine Zeile gelesen.

Der FINDSTR-Befehl im Kopf der FOR-Schleife ließt wegen dem Parameter "^" alle Zeilen mit einem Anfang (dadurch werden alle Zeilen gelesen, auch leere) aus der ersten Eingabedatei. Durch den Parameter /n schreibt er vor jede Zeile die Zeilennummer gefolgt von einem Doppelpunkt. Der Doppelpunkt wird mit delims=: als Trennzeichen für den Tokenizer der FOR-Schleife festgelegt. Durch tokens=1* wird der vorgegebenen Laufvariablen %%a die Zeilennummer und der durch * automatisch erzeugten Laufvariablen %%b der Zeileninhalt zugewiesen.

Der Befehl set /p "line=" in Zeile 10 ließt die zweite Eingabedatei ein, denn diese wird in Zeile 13 des Scripts mit <"%InFile2%" der gesamten FOR-Schleife als Eingabedatei zugewiesen. Damit bei einer leeren Zeile in der zweiten Eingabedatei auch eine leere Zeile in der Ausgabedatei erscheint, wird in Zeile 9 die Variable gelöscht, die den Zeileninhalt aufnimmt.

Durch die Punkte nach den ECHO-Befehlen in den Zeilen 11 und 12 werden im Fall, dass eine der Variablen leer ist, tatsächlich Leerzeilen in die Ausgabedatei geschrieben. Ohne den Punkt nach dem ECHO-Befehl würde sonst die Meldung ECHO ist ausgeschaltet (OFF). in die Ausgabedatei geschrieben.

Falls die erste Eingabedatei weniger Zeilen als die zweite hat, werden aus der zweiten Eingabedatei nur so viele Zeilen gelesen, wie in der ersten Eingabedatei vorhanden sind.

Wenn die zweite Eingabedatei weniger Zeilen als die erste hat, werden für die fehlenden Zeilen Leerzeilen in die Ausgabedatei geschrieben.


7a. Eine Datei incl. Leerzeilen einlesen
@echo off & setlocal

set "InFile=.\Test1.txt"  

for /f "tokens=1* delims=:" %%a in ('findstr /n "^" "%InFile%"') do (  
  echo.%%b
)
Das Einlesen der Datei übernimmt der FINDSTR-Befehl. Damit können mit Hilfe sehr rudimentärer Regular Expressions Zeilen in Dateien gesucht werden, auf die das angegebene Suchmuster passt. Das Zeichen ^ steht für den Zeilenanfang. Dementsprechend passt das Suchmuster auf alle Zeilen. Durch den Parameter /n stellt FINDSTR jeder gefundenen Zeile die Zeilennummer gefolgt von einem Doppelpunkt voran. Der Doppelpunkt wird mit delims=: als Trennzeichen vereinbart. Die Zeilen der Eingabedatei werden wegen tokens=1* in zwei Tokens zerlegt. Das erste (in Laufvariable %%a, hier nicht verwendet) enthält die Zeilennummer und das zweite (in der automatisch erzeugten Laufvariable %%b) den Rest der Zeile nach dem Trennzeichen, also dem Doppelpunkt. Weil zwischen dem ECHO-Befehl und der Laufvariablen %%b ein Punkt steht, wird eine Leerzeile ausgegeben, wenn %%b nichts enthält, wenn also eine Leerzeile aus der Datei eingelesen wurde.

Der Code funktioniert übrigens auch einwandfrei, wenn die Datei Sonderzeichen enthält, die unter gewöhnlichen Umständen vom Batchscript-Interpreter als Steuerzeichen/Befehl angesehen werden. Der Inhalt der Laufvariablen von FOR-Schleifen wird NICHT interpretiert sondern als normaler Text angesehen.


7b. Die Ausgabe eines Befehls incl. Leerzeilen verarbeiten
@echo off & setlocal

set "InFile=.\Test1.txt"  

for /f "tokens=1* delims=:" %%a in ('type "%InFile%" ^| findstr /n "^"') do (  
  echo.%%b
)
Hier wird die Datei mit Hilfe des TYPE-Befehls eingelesen und über eine Pipe an den FINDSTR-Befehl geschickt. Statt TYPE könnte auch ein beliebiges anderes Kommando verwendet werden, z.B. DIR. Die Ausgabe von Leerzeilen wird durch den gleichen Trick wie in Beispiel 7a erledigt.

Der TYPE-Befehl ist übrigens dazu in der Lage, den Inhalt von Unicode-Dateien bei der Ausgabe in die aktuell eingestellte Codepage der Konsole zu konvertieren.


8. Laufvariablen einer FOR-Schleife in einem Unterprogramm verwenden
@echo off & setlocal

set "InFile=.\Test1.txt"  

for /f "tokens=1* delims=:" %%a in ('findstr /n "^" "%InFile%"') do (  
  call :SubRoutine
)

exit /b


:SubRoutine
  for %%z in (DummyLoop) do (
    echo.%%b
  )
exit /b
Als Grundgerüst wird hier nochmals der Code aus Beispiel 7 verwendet. Im Unterschied dazu wird die Ausgabe jedoch im Unterprogramm SubRoutine erledigt. Das besteht nur aus einer Dummy-FOR-Schleife, die lediglich den Zweck hat, die Verwendung von FOR-Laufvariablen zu erlauben - die Laufvariable %%b der FOR-Schleife aus dem Hauptprogramm!

Diese Technik sollte man zwar nur im äußersten Notfall benutzen (evtl. funktioniert dieser Trick in zukünftigen Versionen von CMD.exe nicht mehr), aber es ist gut zu wissen, dass diese Möglichkeit existiert.


9. Beschleunigung von FOR-Schleifen, die Ausgaben in eine Datei schreiben
@echo off & setlocal

set "OutFile=.\Eval.txt"  
set "InFiles=.\*.log"  
set "SearchPattern=Error"  

(for %%f in ("%InFiles%") do (  
   for /f "tokens=* delims=" %%l in ('findstr /i /c:"%SearchPattern%" "%%f"') do (  
     echo %%f: %%l
   )
)) > "%OutFile%"  
Der Code ließt im aktuellen Verzeichnis alle Dateien mit der Erweiterung log ein und sucht in ihnen Zeilen, die den Begriff Error (ohne Berücksichtigung der Groß-/Kleinschreibung) enthalten. Gefundene Zeilen werden in eine Ausgabedatei geschrieben (mit dem vorangestellten Namen der Datei, aus der sie stammen).

Die Umleitung der Ausgabe in der letzten Zeile bezieht sich durch die Klammerung der beiden FOR-Schleifen auf den gesamten Codeblock innerhalb der Klammern. Dadurch muss die Ausgabedatei nur einmal geöffnet werden, was bei vielen Schreiboperationen den Scriptlauf sehr stark beschleunigt. Ich hatte schon Anwendungsfälle, wo durch diese Technik die Laufzeit von 15 Minuten auf 10 Sekunden verkürzt werden konnte.


10. Array-Simulation mit mehr als 31 Array-Elementen
In Beispiel 11 wurde bereits eine Array-Simulation gezeigt. Die Indizierung des Arrays wurde dort mittels der TOKENS-Option der FOR-Schleife durchgeführt, wodurch das Array aber höchstens 31 Elemente haben kann. Der folgende Schnipsel zeigt, wie man diese Begrenzung überwindet und wie man eine FOR-Schleife als auszuführenden Befehl in die Klammer einer äußeren FOR /F -Schleife schreibt.
@echo off & setlocal

::Array füllen
set "Array="E01";"E02";"E03";"E04";"E05";"E06";"E07";"E08";"E09";"E10";"E11";"E12";"E13";"E14""  
set "Array=%Array%;"E15";"E16";"E17";"E18";"E19";"E20";"E21";"E22";"E23";"E24";"E25";"E26";"E27""  
set "Array=%Array%;"E28";"E29";"E30";"E31";"E32";"E33";"E34";"E35";"E36";"E37";"E38";"E39";"E40""  
set "Array=%Array%;"E41";"E42";"E43";"E44";"E45""  

::Auszulesenden Index und Ergebnisvariable initialisieren
set /a Idx=42
set "Item="  

::Array-Element auslesen
for /f "tokens=1* delims=:" %%a in ('^(for %%a in ^(%Array%^) do @echo %%a^) ^| findstr /n "^"') do (  
  if %%a equ %Idx% (
    set "Item=%%b"  
  )
)

::Angehängtes Leerzeichen entfernen
for %%a in (%Item%) do set "Item=%%~a"  

::Ergebnis ausgeben
echo.%Item%
Das Array wird mit der inneren FOR-Schleife Zeile für Zeile ausgegeben. Der FINDSTR-Befehl setzt durch den Parameter /N Zeilennummern und einen Doppelpunkt vor jedes Array-Element. Zeilennummer und Zeileninhalt werden von der äußeren FOR-Schleife durch die Optionen tokens=1* delims=: voneinander separiert. In der Laufvariablen %%a ist die Zeilennummer und in der Laufvariablen %%b der Zeileninhalt gespeichert. Wenn die Zeilennummer gleich dem gewünschten Index ist, wurde das Element gefunden. Dummerweise hängt der Batchscript-Interpreter noch ein Leerzeichen an den Zeileninhalt in %%b, das durch die Konstruktion in Zeile 21 entfernt wird.


11. Bestimmte Zeilen aus einer Datei extrahieren
In Beispiel 9 hatte ich erwähnt, dass man mit FOR /F zwar eine bestimmte Anzahl Zeilen vom Dateianfang aus überspringen kann, es jedoch keine Möglichkeit gibt, eine bestimmte Anzahl Zeilen am Ende einer Datei zu ignorieren oder nur eine bestimmte Anzahl Zeilen der Datei zu verarbeiten. Manchmal wäre es jedoch schon praktisch, ab einer bestimmten Dateizeile einen Block von Zeilen zu extrahieren und nur diese Zeilen weiterzuverarbeiten. Genau das leistet das folgende Script.
@echo off & setlocal

::Eingabedatei sowie Start- und Endzeile festlegen
set "InFile=Logfile.log"  
set "StartLine=5"  
set "StopLine=10"  

::Der Wert für die Startzeile muss korrigiert werden
set /a StLn=StartLine-1

::Datei bis zur angegebenen Endzeile einlesen, die gewünschte Anzahl Zeilen am
::Anfang ignorieren und nur die gewünschten Zeilen ausgeben
for /f "skip=%StLn% tokens=1* delims==" %%a in ('^(for /l %%a in ^(1,1,%StopLine%^) do @^(set "TmpVar=" ^& set /p "TmpVar=" ^& set TmpVar 2^>NUL^) ^|^| echo TmpVar^=^) ^< "%InFile%"') do (  
  echo(%%b
)
In dem Schnipsel werden einige bereits vorgestellte Techniken verwendet (innere FOR-Schleife im Kopf einer äußeren FOR-Schleife (Praxistipp 10), Einlesen einer Datei innerhalb einer FOR-Schleife durch Eingabeumleitung für die gesamte Schleife (Praxistipp 6) und Ausgabe von Variableninhalten innerhalb einer FOR-Schleife durch den SET-Befehl (Beispiel 7)).

Mit der inneren FOR-Schleife wird die Datei bis zur angegebenen Endzeile eingelesen. Jede eingelesene Zeile wird mit set /p "TmpVar=" an die Umgebungsvariable TmpVar zugewiesen, worauf der Variableninhalt mit set TmpVar ausgegeben wird. Beim Einlesen einer Leerzeile wird der Wert von TmpVar jedoch nicht verändert, der bisherige Wert bleibt erhalten. Damit der Inhalt der vorherigen Zeile nicht nochmals ausgegeben wird, wird TmpVar vor der Zuweisung des Inhalts einer Zeile mit set "TmpVar=" gelöscht. Damit in diesem Fall bei der Ausgabe des Variablenwerts keine Fehlermeldung ausgegeben wird (á la Umgebungsvariable existiert nicht), wird der Standard-Fehlerkanal auf das NUL-Device umgeleitet. Außerdem kann die fehlgeschlagene Ausführung von set TmpVar dazu benutzt werden, den Text TmpVar= auszugeben, damit die äußere FOR-Schleife an dieser Stelle eine Leerzeile ausgibt.

Die Ausgabe der inneren FOR-Schleife sieht ungefähr so aus:
TmpVar=Inhalt von Zeile 1
TmpVar=Inhalt von Zeile 2
TmpVar=                     <- Hier ist in der Eingabedatei eine Leerzeile
TmpVar=Inhalt von Zeile 4
...
Hier muss jetzt alles links vom Gleichheitszeichen entfernt und die gewünschte Anzahl Zeilen bis zur Startzeile übersprungen werden. Das macht die äußere FOR-Schleife, indem der Tokenizer mit den Optionen tokens=1* und delims== entsprechend eingestellt wird und mit der Option skip=... die nicht gewünschten Zeilen herausgefiltert werden.

Es gibt übrigens eine Einschränkung für das Script: Da die FOR /F-Schleife bei der Option SKIP= den Wert 0 nicht toleriert, kann man die Quelldatei nicht von Zeile 1 bis X sondern nur mindestens von Zeile 2 an verarbeiten. Für die Verarbeitung von Zeile 1 bis X muss die äußere FOR-Schleife entfernt und die innere entsprechend umgeschrieben werden, damit sie auch Stand-alone läuft (Escape-Zeichen entfernen).

Content-ID: 155681

Url: https://administrator.de/tutorial/tutorial-zur-for-schleife-155681.html

Ausgedruckt am: 21.12.2024 um 10:12 Uhr

bastla
bastla 24.11.2010 um 22:55:54 Uhr
Goto Top
Hallo Friemler!

Gratuliere zu diesem sehr umfangreichen und sehr gelungenen Tutorial. face-smile

Grüße
bastla
Nagus
Nagus 25.11.2010 um 09:23:45 Uhr
Goto Top
Hi Friemler,

DANKE! face-smile

Gruß Nagus
Florian.Sauber
Florian.Sauber 25.11.2010 um 17:09:55 Uhr
Goto Top
Vorbildlich, Friemler! Daumen hoch!

LG Florian
90776
90776 25.11.2010 um 21:19:51 Uhr
Goto Top
der Kandidat hat 100 Punkte


schön geschrieben

Grüsse
Switcher
jeb-the-batcher
jeb-the-batcher 25.11.2010 um 22:14:29 Uhr
Goto Top
Hallo Friemler,

recht langer und ausführlicher Beitrag, sehr gut gelungen.

Mir fehlt nur der Abschnitt: "FOR extrem" mit den Grenzen und Erklärungen die richtig in die Tiefe gehen.
Z.B. das man nur mit DisabledDelayedExpansion den Inhalt eines FOR-Parameters sicher verwenden kann (alle Kombinationen von Spezial & Escapezeichen) mit EnabledDelayedExpansion ist das nicht möglich, denn bereits ein "hallo!" scheitert,
extrem wäre ein &^!"&!^"""&!^"""&^!, das ist ohne DelayedExp praktisch nicht zu beherrschen.

setlocal DisableDelayedExpansion
FOR /F "delims=*" %%a in ("hallo ^caret!")  do (  
   echo %%a
   set var=%%a
)

Um dann var aber sicher (unabhängig vom Inhalt) benutzen zu können, muss man auf EnabledDelayedExpansion umschalten.
Mit call echo %var% bekommt man sonst ganz schnell Probleme
setlocal DisableDelayedExpansion
FOR /F "delims=*" %%a in ("hallo ^caret!")  do (  
    set var=%%a
    setlocal EnableDelayedExpansion
    set "var=!var:h=b!"  
    echo !var!
    endlocal
)

Oder was geht so? Oder wie und wann wirkt die Expansion im FOR Befehl?
setlocal EnableDelayedExpansion
set eins=1
set zwei=2
set drei=a
set "vier=set /p .=hallo < nul"  
FOR /F "tokens=!eins! delims=!zwei!" %%!drei! in ('!vier!')  do echo %%a  
Hierbei scheitert die Expansion von !eins! !zwei! und !drei!, die von !vier! klappt und hat zudem den Vorteil,
dass die Spezialzeichen nicht escaped werden müssen.
Das eins,zwei,drei scheitern liegt daran, dass der FOR-Befehl anders als andere Befehle für die eigenen Parametern generell keine DelayedExpansion durchführt,
dass scheint daran zu liegen, dass der Befehl bereits sehr früh vom Parser erkannt werden muss, um die ganze Klammerlogik aufrecht erhalten zu können (wie beim IF Befehl).

FOR-Loops brechen ab, sobald man ein goto verwendet, selbst wenn das Ziel innerhalb der Loop liegt.
for /L %%n in (1,1,100) DO (
  echo %%n
  goto :label
  :label
  echo %%n
)
echo ende
------------ AUSGABE ------
1
%n
ende

Aber Abbruch ist hier nicht mit einem sofortigem Abbruch zu verwechseln, hier dauert der Abbruch schlappe 16 Sekunden!
for /L %%n in (1,1,1000000) DO (
  echo %%n - %time%
  goto :xx
  :xx
  echo %%n - %time%
)
echo ende
------------ AUSGABE ------
1 - 22:28:05,73
%n - 22:28:21,09
ende

Und dann gibt es da noch ... und ... (eben das was in "FOR extrem" stehen sollte)

Grüße
jeb
Friemler
Friemler 26.11.2010 um 11:23:48 Uhr
Goto Top
Hi @all,

zunächst mal "Danke!" an alle für Eurer Lob, freut mich, dass das Tutorial so gut aufgenommen wurde.


@jeb
Danke für Deine Anregungen. Natürlich hast Du vollkommen recht, mein Tutorial ist keine vollständige Abhandlung zur FOR-Schleife. Deine Anmerkung zum Thema "Verwendung von verzögert erweiterten Variablen im Kopf der FOR-Schleife" gehört aber auf jeden Fall noch rein. Evtl. auch die Sache mit den GOTO-Befehlen.

Bei der Erstellung der Anleitung dachte ich eher an die Batch-Neulinge, die zunächst mal auf der Suche nach grundlegenden, verständlich und ausführlich dargestellten Informationen zu FOR sind. Das, was Dir vorschwebt, ist eher was für ein separates Tutorial "FOR for Runaways", vor allem weil das Tut in der jetzigen Form schon eine beträchtliche Länge hat.

Wie Du Dir vorstellen kannst, war die Erstellung des Tutorials schon etwas zeitaufwändig. Da ich mich z.Z. erstmal um ein anderes Projekt kümmern muss, falle ich im Moment als Autor für ein weiterführendes Tutorial aus. Aber Du hast ja schon mit Deinen Batch-Secrets bewiesen, dass Du für so etwas ebenfalls der richtige Mann wärst. Vielleicht lesen wir demnächst was von Dir zu dem Thema?

Gruß
Friemler
jeb-the-batcher
jeb-the-batcher 08.06.2011 um 00:11:27 Uhr
Goto Top
Hallo mal wieder,

da ich in der Zwischenzeit noch ein wenig dazu gelernt habe, noch ein paar Infos.

EOL bezeichnet den End Of Line Buchstaben, wie der Name schon sagt gibt es nur einen, aber es gibt IMMER einen, sprich man kann EOL nicht einfach auf <Leer> setzen.
ein FOR /F "EOL=" ... bewirkt, dass EOL jetzt auf ein " gesetzt wurde.
Das kann manchmal recht unpraktisch werden, da jede Zeile die mit dem EOL-Buchstaben beginnt weggeworfen wird.

Allerdings gibt es zwei Ausnahmen:
Wenn der EOL-Buchstabe auch in den DELIMS Buchstaben vorkommt, ist der EOL-Mechanismus wirkungslos.
Das ist schon ganz nett, hilft aber auch nichts wenn man DELIMS leer hat.

Dann hilft nur noch den EOL auf <Linefeed> zu setzen, er ist dann zwar nicht leer, aber das spielt keine Rolle, da <Linefeed> ohnehin das Zeilenende markiert,
Allerdings ist es nicht ganz trivial den EOL auch tatsächlich auf <Linefeed> zu setzen.
echo on
FOR /F ^"tokens^=1^ EOL^=^  

^ delims^=^" %%a in (myfile.txt) do echo %%a  

Sieht schlimm aus, aber nur weil man das <Linefeed> innerhalb von Anführungszeichen erzeugen muss (was eben nicht so direkt geht), nach der Ausgabe mit ECHO ON sieht es schon recht normal aus.

Dann wäre da noch der Zugriff auf die Laufvariablen der FOR-Schleifen.
Wenn man z.b. mit einem call :func aus einer FOR-Schleife rausspringt kann man nicht mehr auf die Laufvariablen zugreifen, aber mit einem Trick gelingt es dann doch wieder.

@echo off
for %%s in ("s-content") do (  
	echo loop1 loopvar-s=%%s
	call :test
)
exit /b

:test
echo test1 loopvar-s=%%s
for %%a in ("a-content") do (  
	echo loop2 loopvar-a=%%a
	echo loop2 loopvar-s=%%s
)
exit /b
Sprich in einer FOR-Schleife sind immer ALLE Laufvariabeln erreichbar(außer denen die doppelt vergeben wurden), auch wenn man sich in einer Funktion befindet.

Grüße
jeb
Skyemugen
Skyemugen 09.06.2011 um 09:17:25 Uhr
Goto Top
Aloha jeb,

das mit den Laufvariablen ist interessant, so könnte man alle Laufvariablen nutzen, ohne die Parameter (wie sonst genutzt call :test "%%s" + %1 im Ablauf) irgendwann shiften zu müssen.

Aber zum EOL ... ich bin auf den ersten Fall gespannt, wo auch diese Variante dann gegen die Wand fährt face-wink ich persönlich verwende bisher wenn dann ein Zeichen, was ich glaube, dass es nicht vorkommen wird - z.B. EOL=€ oder EOL=¬

greetz André
pieh-ejdsch
pieh-ejdsch 15.08.2011 um 23:15:46 Uhr
Goto Top
moin,

Wie man Befehle innerhalb einer Forschleife zerbröselt um die vielen EscapeZeichen dazwischen-zu-Friemeln wissen wir ja. Der Fehlerteufel Freut sich wenn mal eines davon fehlt!
Die ganze Befehlsverkettung hat doch grad noch im Test ohne die drumherumgebastelte ForSchleife Funktioniert.
so oder ähnlich macht sich meist Frust breit und die Lust an der Stelle Weiterzumachen schwindet auch mit der Zeit wenn die Augen ermüden.

Generell kann man es so halten das der Befehl mit Verkettung anderer Befehle genauso wie der Test ohne die Forschleife geschrieben wird und in der ForSchleife nicht extra mit jedem zu escapenden Zeichen Versehen werden muss.
den Befehl(satz) nicht nur in einfache AnführungsZeichen einschliessen sondern erst in Doppelte AnführungsZeichen und darum in Einfache einschliessen.
FOR /F ["Optionen"] %Variable IN ( ' " Befehl1 [Parameter] | Befehl X && Befehl Y " ' ) DO Befehl2 [Parameter]

zB. beim Filtern und Zählen von Dateien
setlocal
set "User=x-Tra"  
for /f %%i in (' " Dir /b *.bc? 2>nul|findstr /v /r /c:"[.]bco$"|findstr /v /r /c:"^%User%[.]"|find /v /c "" 2>nul " ') do echo %%i andere Dateien Vorhanden  

Vergleichbar ist das mit :
cmd /c"Befehl"
cmd /k"Befehl"
das mit der For in der For mit delayedexpansion ist ein Spezialfall - da müssen nur noch die Analyseschlüsselwörter = (Sonderzeichen) escaped werden.
setlocal EnableDelayedExpansion
set eins=1
set zwei=2
set drei=a
set "vier=set /p .=hallo < nul"  
for /f "delims=" %%z in ( ' " FOR /F "tokens^=!eins! delims^=!zwei!" %%!drei! in (' " !vier! " ')  do @echo %%a " ' ) do echo %%z  

Gruß Phil
Friemler
Friemler 16.08.2011 um 11:09:18 Uhr
Goto Top
Hallo Phil,

danke für die neuen Erkenntnisse. Ein Hinweis darauf ist schon ins Tutorial eingebaut.

Gruß
Friemler
Wolfsjux
Wolfsjux 01.04.2015 aktualisiert um 09:32:48 Uhr
Goto Top
Danke für die hervorragenden Beiträge. Hier noch ein hübsches Beispiel um festzustellen (z.B.: beim Autostart), welche Laufwerke aktuell angeschlossen sind:
for %%x in (A B C D E F G H I J K L M N O P Q R S T U V W X Y Z) do if exist %%x:\ echo Das Laufwerk ist angeschlossen %%x
Gruß Wolf
evinben
evinben 15.03.2016 aktualisiert um 18:48:59 Uhr
Goto Top
wäre es irgendwie möglich in delims= eine Trennzeichenkette zu erzwingen, also dass dann die dort eingegebenen Zeichen nur in der angegebenen Kombination 1:1 - sogar unter Berücksichtigung von Groß-Kleinschreiben - gültig werden?
Z. B. etwa "Gr." einzugeben und dabei nach der Zeichenkette "Gr." suchen und so die gefundene Strings in Tokens aufteilen? Weil so wäre es in manchen Texten sicherere/zuverlässiger (als bloß nach Punkt "." zu suchen, weil dieser im Text in vielen Zeilen öfters willkürlich vorkommt könnte und "G" und "r" einzeln geht so natürlich gar nicht, weil die Buchstaben fast überall im Text unsystematisch vorhanden sind)

Gruß
evinben
bastla
bastla 15.03.2016 aktualisiert um 23:38:43 Uhr
Goto Top
Hallo evinben!

Per for /f lässt sich das nicht realisieren, aber sieh Dir vielleicht einmal "hier) dazu an ...

Grüße
bastla
Hein-nieH
Hein-nieH 18.04.2017 um 18:33:46 Uhr
Goto Top
Hallo,

das Tutorial zur For-Schleife ist echt super.
Nun habe ich als anfänger etwas herumexperimentiert.

Das Beispiel 11 funktioniert bei mir nicht.

for /f "tokens=%Index%" %%i in ("%HexDigits%") do (

Wenn innerhalb des Schleifenkörpers das if-statement steht steigt das Skript aus.
Ich nutze Windows 7.
Habe auch das Skript 1:1 kopiert. Es steigt ebenfalls im Schleifenkörper bei if aus.
Woran kann das liegen?

Muss ich da möglicherweise noch Einstellungen in cmd vornehmen?
Ueber einen Tipp würde ich mich sehr freuen.

Gruss Hein_nieH
Hein-nieH
Hein-nieH 18.04.2017 um 18:54:25 Uhr
Goto Top
Fehler gefunden

Bei dem If-Statement darf zwischen dem Schluesselwort if und dem Schalter /I KEIN Leerzeichen stehen.

Gruss Hein_nieH
Hein-nieH
Hein-nieH 18.04.2017 um 19:06:39 Uhr
Goto Top
... mist, zu frueh gefreut ( bei Beispiel 11)

for /f "tokens=%Index%" %%i in ("%HexDigits%") do (
if /i"%Digit%" EQU "%%i" (

beim IF Statement steigt das Script aus.
Weiss jemand warum

Lasse ich das Leerzeichen weg, also if/i dann kommt die Fehlermeldung, dass if nicht verarbeitet werden kann.

Wer kann mir hier weiterhelfen?
Wolfsjux
Wolfsjux 18.04.2017 um 21:59:48 Uhr
Goto Top
Hallo Hein,

verwendest du xxx.bat scripts.
Bei mir geht es noch so wie in Win8, jetzt auch in Win10! Win7 weiß ich nicht.

@echo off
rem Dos-Befehls-Sammlung, die funktioniert, erstellt von Jung 15.5.15

for %%x in (A B C D E F G H I J K L M N O P Q R S T U V W X Y Z) do if exist %%x:\ echo Das Laufwerk gibt es %%x
pause
:Ende
Echo * Ende der Procedur xxxxxxxx Ende

Gruß Wolf
Hein-nieH
Hein-nieH 19.04.2017 um 10:21:25 Uhr
Goto Top
Hallo Wolf,

ja ich nutze xxx.bat Scripts.
Ich hoffe, dass sich die Ursache für den Ausstieg noch finden laesst.

Gruss Hein_nieH
132895
132895 19.04.2017 aktualisiert um 10:30:54 Uhr
Goto Top
if /i"%Digit%" EQU "%%i" (
Hinter dem /i fehlt das Leerzeichen.

Gruß
Hein-nieH
Hein-nieH 19.04.2017 um 10:30:03 Uhr
Goto Top
Hurra, Fehler gefunden

Der Skriptausstieg hat nichts mit der For-Schleife oder IF-Anweisung zu tun.

Ursache war die Zeile set "Digit=%HexNum:~0,1%" . Da hatte ich ein Anführungszeichen vergessen.
Jetzt funktioniert es.

Gruss Hein_nieH
Wolfsjux
Wolfsjux 19.04.2017 um 10:39:57 Uhr
Goto Top
Na Glückwunsch, neue Befehlsfolgen immer mit "@echo on" und vielen "pause" starten - dann erkennt man den falschen Befehl.
Gruß Wolf
Qniemiec
Qniemiec 11.08.2020 aktualisiert um 12:09:00 Uhr
Goto Top
Hallo allerseits, gehöre mit meinem Festhalten an Windows XP und meinem 16-Bit-PowerBasic-Compiler aus den 1990ern wahrscheinlich zu den Dinosauriern in dieser Runde, versuche mich aber wie schon zu DOS-Zeiten immer wieder gern darin, Probleme allein mit den asketischen Bordmitteln der jeweiligen Kommandozeilenumgebung zu lösen, manchmal dann auch mit einer quasi die letzten Meter zum Erfolg überbrückenden kleinen EXE aus meinen PowerBasic-Compiler, wobei Windows' CMD.EXE allerdings wirklich so einiges mehr zu bieten hat als die gute alte COMMAND.COM. face-smile Und aus diesem Erfahrungshorizont heraus hier noch ein paar vielleicht nützliche Anmerkungen und Ergänzungen:

1) In Friemlers tollen Tutorial (Hut ab!) lesen wir unter Pkt.5: "Nachteilig an der Sache ist, daß ein Anwender gezwungen wäre, so eine Konfigurationsdatei mit einem Editor zu schreiben, der im DOS-/ASCII-Mode abspeichern kann, [...] denn die Befehle der Kommandozeile arbeiten immer noch im ASCII-Modus. Es muss also ein ANSI=>ASCII Konverter her, dann kann man Konfigurationsdateien mit Notepad schreiben." Oder eben _nicht_ mit dem Notepad, weil das nur ANSI oder UTF-8/UTF-16 kann! Habe also, als ich irgendwann auf Windows umsteigen musste, anfangs auch lange nach so etwas gesucht, also einem im Idealfall zu Windows' eigenen Bordmitteln gehörenden Editor, der sowohl ANSI als auch ASCII kann, und das ist eben nicht das Windows-Notepad, sondern das Windows-Wordpad! face-smile Das kann nämlich ANSI, UTF-16, aber auch ASCII und, wenn man 'n bissel was formatieren möchte, RTF (und das nicht nur schreiben, sondern auch lesen, s.u.)!

savetxts

Also quasi das ideale Bindeglied zwischen DOS- und Windows-Texten. So dass, wenn ich seitdem irgendwelche Batchdateien schreibe, ich das zunächst einmal immer mit dem Wordpad im RTF-Format tue (und dabei, um irgendwas im Quelltext hervorzuheben, auch schön mit Farben, Fett, Kursiv und Unterstreichen arbeiten kann), und nachdem ich das dann im RTF-Format abgespeichert hab, speichere ich's mit "Speichern unter" jedesmal auch nochmal mit der Option "Textdokument - MS-DOS-Format" als ausführbare Batch mit der von mir dabei vorzugebenden Extension BAT oder CMD (weil das Wordpad selber natürlich immer erstmal TXT vorschlägt). Ist für mich, seitdem ich draufgekommen bin, der Königsweg, umso mehr, als ich dadurch auch immer zwei Versionen meiner Batch habe, eine reich illustrierte Dokumentation in Form der RTF, und dann nochmal die ausführbare Datei als BAT oder CMD.

2) Zu dem Pkt. "Erweiterung von Laufvariablen" muss ich, was "%~sI" angeht, leider was korrigieren: Diese Erweiterung funktioniert so wie beschrieben leider nur, wenn alle im Suchpfad vorkommenden Verzeichnis- und Dateinamen DOS-konform sind, also zB. keine der neuerdings so beliebten (langen) Gedankenstriche oder andere Zeichen enthalten, mit denen DOS nix anfangen kann: ist letzteres der Fall, verbleibt dieser Teil des Pfads dann leider im i.d.R. langen Original. So dass der einzige mir bekannte Weg, an den 8+3-Namen auch wirklich jeder Datei zu kommen, die Option /x des DIR-Befehls ist (was zB. für mich speziell vor allem dann von Interesse ist, wenn ich eine solche, aber auch jede andere Datei mit langem Namen mit einem meiner alten DOS-Programme öffnen will, die ja nur 8+3-Namen können - da muss ich dann zunächst mit DIR /x den Kurznamen der zu öffnenden Datei freipräparieren und diesen dann in einem zweiten Schritt als Parameter an meine DOS-EXE weiterreichen).

3) Ebenfalls noch zu Pkt. "Erweiterung von Laufvariablen", muss ich zu "%~pI" auch noch was ergänzen: dieser Term extrahiert zwar definitionsgemäß den Pfad von %%I, interpretiert dabei allerdings nur alles zwischen dem ersten und letzten Backslash Befindliche als Pfad, alles ihm folgende dagegen als Dateiname - bei einer Pfadangabe der Form "C:\dir1\dir2\dir3.2" würde "%~pI" daher nur der String "\dir1\dir2\" als Pfadangabe zurückliefern, das letzte Unterverzeichnis "dir3.2" dagegen als Dateiname interpretieren und damit - als Verzeichnis! - unterschlagen, und selbst wenn man "%%~pI" nun zu "%%~pnI" erweitern wollte, würde die abschließende "2" dabei auch wieder, da nun als Extension behandelt, durchs Raster fallen. Man kann also auch hier, um wirklich den kompletten Verzeichnispfad zu erhalten, ggf. mit "%%~pnxI" arbeiten müssen.

Erinnert mich im übrigen alles so'n bissel an die alten Zeiten, als man die richtig kleinen und richtig schnellen Programme noch gleich in Assembler schrieb und einen da praktisch noch weniger vor dem Abgrund schützte als es die heutige CMD.EXE tut - da kommt man (wenigstens meist) ohne einen Neustart aus. face-smile

Man liest sich,
Qniemiec
evinben
evinben 12.08.2020 aktualisiert um 12:07:36 Uhr
Goto Top
Hallo @Qniemiec,

deine Ergänzung ist willkommen - klar und verständlich beschrieben, was dich so auf dem Herzen bewegt.

Für viele hier in Forum ist das Windows eigene Notepad (bzw. Windows Editor) bloß eine "neutrale" Benennung, um nicht irgendwelche favorisierte Textbearbeitungsprogramme zu erwähnen, weil diese Möglichkeiten mittlerweile ("wie der Sand am Meer") unzählig sind. Mensch neigt sich bei Empfehlungen zu distanzieren - die sogenannte "Beratungsresistenz" ist stark gewachsen und gewöhnlich alles stößt erstmals auf Skepsis. Viele sind immuner geworden gegen alles, was nach Werbung klingen könnte. Nütz vom Unnütz ist ohne die eigene Erfahrung kaum zu überblicken.

Sehr viele nutzen aus einfachen und praktischen Gründen Notepad++. Ich selbst bin - wie auch viele Anwender weltweit - damit zufrieden, wegen der einfachen Handhabung und des leichten Gewichts (auch sind mir keine Ärger wie essentielle technische Probleme, Werbung und Wartungskosten bekannt). Im Notepad++ Support-Forum habe ich bisher nur einen Verbesserungsvorschlag abgegeben und seit etwa 3 Monaten bis heute immer noch unbeantwortet geblieben. Das war es aber schon meinerseits zum Meckern über das Programm.

Kurz zum WordPad
"Ist für mich, seitdem ich draufgekommen bin, der Königsweg, umso mehr, als ich dadurch auch immer zwei Versionen meiner Batch habe, eine reich illustrierte Dokumentation in Form der RTF, und dann nochmal die ausführbare Datei als BAT oder CMD."
Quasi "ala Compiler" face-smile auf einfacher Art - mit Notizen, Formatierungen, Anhängen, Hyperlinks … .
Früher, zw. 2012 - 2013, habe ich paar Monate genau so ein Szenario mit Windows WordPad gehandhabt, seit ich jedoch Notepad++ benutze, will aufgrund viele Umständen/Nachteilen einfach so keinesfalls zurück (vielleicht bloß ab und zur Not, falls mal auf irgendeinem System gerade doch kein Notepad++ vorhanden ist und weder meine Werkzeuge als Datensammlung noch Internet verfügbar sind oder verfügbar sein dürfen).
Manche Kommentare dürfen auch in Batch-Skripten hinterlegt werden und in Notepad++ gelingt dies automatisch farblich (je nachdem wie die Farben für die eigene Batch-Skriptsprache konfiguriert werden).

Aber falls du immer noch mit WordPad sehr überzeug und weiterhin begeistert bist, will ich dir die Freude nicht entnehmen und anbei paar Tipps aus 2012 noch:

"Batch-Dateien standardmäßig mit WordPad bearbeiten.reg"
Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\batfile\shell\edit]
[HKEY_CLASSES_ROOT\batfile\shell\edit\command]
;"%ProgramFiles%\Windows NT\Accessories\wordpad.exe" "%1"  
@=hex(2):22,00,25,00,50,00,72,00,6f,00,67,00,72,00,61,00,6d,00,46,00,69,00,6c,\
  00,65,00,73,00,25,00,5c,00,57,00,69,00,6e,00,64,00,6f,00,77,00,73,00,20,00,\
  4e,00,54,00,5c,00,41,00,63,00,63,00,65,00,73,00,73,00,6f,00,72,00,69,00,65,\
  00,73,00,5c,00,77,00,6f,00,72,00,64,00,70,00,61,00,64,00,2e,00,65,00,78,00,\
  65,00,22,00,20,00,22,00,25,00,31,00,22,00,00,00

[HKEY_CLASSES_ROOT\batfile\shell\Notepad]
[HKEY_CLASSES_ROOT\batfile\shell\Notepad\command]
;%SystemRoot%\System32\NOTEPAD.EXE %1
@=hex(2):25,00,53,00,79,00,73,00,74,00,65,00,6d,00,52,00,6f,00,6f,00,74,00,25,\
  00,5c,00,53,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,00,5c,00,4e,00,4f,00,\
  54,00,45,00,50,00,41,00,44,00,2e,00,45,00,58,00,45,00,20,00,25,00,31,00,00,\
  00

"Batch-Dateien standardmäßig mit WordPad bearbeiten_Zurücksetzen.reg"
Windows Registry Editor Version 5.00

;Anwendung festlegen, mit welcher die .bat-Dateien standardmäßig bearbeitet werden sollen:
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[HKEY_CLASSES_ROOT\batfile\shell\edit\command]
;%SystemRoot%\System32\NOTEPAD.EXE %1
@=hex(2):25,00,53,00,79,00,73,00,74,00,65,00,6d,00,52,00,6f,00,6f,00,74,00,25,\
  00,5c,00,53,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,00,5c,00,4e,00,4f,00,\
  54,00,45,00,50,00,41,00,44,00,2e,00,45,00,58,00,45,00,20,00,25,00,31,00,00,\
  00

;Zusätzliche Anwendung als Alternative festlegen bzw. entfernen
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[-HKEY_CLASSES_ROOT\batfile\shell\Notepad]
[-HKEY_CLASSES_ROOT\batfile\shell\Notepad\command]
;%SystemRoot%\System32\NOTEPAD.EXE %1
;@=hex(2):25,00,53,00,79,00,73,00,74,00,65,00,6d,00,52,00,6f,00,6f,00,74,00,25,\
  00,5c,00,53,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,00,5c,00,4e,00,4f,00,\
  54,00,45,00,50,00,41,00,44,00,2e,00,45,00,58,00,45,00,20,00,25,00,31,00,00,\
  00

"Optionen von WordPad setzen.reg"
Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Applets\Wordpad\Options]

;Statusleiste anzeigen
"ShowStatusBar"=dword:00000000  

;Lineal anzeigen
"ShowRuler"=dword:00000000  

"Units"=dword:00000001  
"Maximized"=dword:00000000  

;Am Fenster umbrechen
;Noch unbekannte Einstellung:	"FrameRect"=hex:50,01,00,00,80,00,00,00,bb,05,00,00,e9,03,00,00  
"Wrap"=dword:00000001  

"PageMargin"=hex:08,07,00,00,a0,05,00,00,08,07,00,00,a0,05,00,00  
"PrintPageNum"=dword:00000001  
"DefaultFormat"=dword:00000005  
Qniemiec
Qniemiec 12.08.2020 um 13:41:24 Uhr
Goto Top
Hallo Evinben, danke erstmal für Dein Reply ink. der Registry-Patches, und klar, da gibt's natürlich endlos viele Alternativen: mein "Spleen" war es einfach zu schauen, ob es auch "mit ohne alles", wie der Berliner sagt, geht, also ohne irgendwelche weiteren Programme. Denn wenn's mal was Komplizierteres ist, zB. irgendwelches Sortieren oder spaltenweises Ersetzen usw., nehme ich dann natürlich auch Zuflucht zu Extraprogrammen wie Office & Co., meine Frage dagegen war, wie weit man kommt, wenn man wirklich nur das nackige Windows hat .
Man liest sich, face-smile
Qniemiec
6391274860
6391274860 25.05.2023 um 10:41:59 Uhr
Goto Top
Hallo zusammen,

Beispiel 6
warum funktioniert der Befehl nicht:
for /d %%v in (Z:\*) do forfiles /p %Verz% /S /M *.* /D -30 /C "cmd /c del @File"

Davor setze ich die Variable für %Verz% mit:
set Verz=\Daten\Lokal\

Das Verzeichnis existiert auf Z:\ und ist ein Unterverzeichnis in jedem Mitarbeiterverzeichnis
zkDummy
zkDummy 15.09.2023 um 13:22:31 Uhr
Goto Top
Unter Windows 11 Home wird die FOR-Schleife nicht durchlaufen, wenn eine SKIP-Angabe größer als die Anzahl der Datensätze in einer line sequential Datei.
Kann das bitte jemand bestätigen?

Hintergrund ist, dass ich versuche mit einer FOR-Schleife festzustellen, ob eine Datei in-use ist. Wenn die Datei nicht in-use ist, so wird natürlich die ganze Datei eingelesen. Dies wollte ich mit dem Skip vermeiden.
pieh-ejdsch
pieh-ejdsch 03.10.2023 um 10:47:55 Uhr
Goto Top
moin zkDummy,

ein Skip überspringt die vorherigen Zeilen.
Wenn die Zeilen danach leer oder keine mehr vorhanden sind, wird es auch keine Ausgabe geben.
zkDummy
zkDummy 03.10.2023 um 17:44:27 Uhr
Goto Top
Hallo pieh-ejdsch.
Danke für die Antwort.

Kann man mit Batch-Befehle(n) feststellen, ob eine Datei in-use ist?