bierfreund
Goto Top

Errorlevel wird in for-Schleife (Windows Batch) nicht gesetzt?

Hallo,
ich möchte mir einen Batch schreiben, der alle .rar-Dateien eines Ordners entpackt, falls kein Fehler auftritt eine Weiterverarbeitung durchführt und die entsprechende .rar-Datei löscht. Ich bin dabei allerdings auf das Problem gestossen, dass der Errorlevel in meiner for-Schleife nicht gesetzt wird.
Zum Testen habe ich mir mal eine fehlerfreie (1test_ok.rar) und eine fehlerhafte (2test_fehler.rar) .rar-Datei plus ein Testskript, das die Dateien zuerst einzeln verarbeitet und anschließend in der for-Schleife. Ich werde daraus allerdings nicht schlau.
Hier zuerstmal der code des Testskriptes:
@echo off
set WinRarExec=D:\WinRAR\rar.exe
echo ----------------------
echo : Einzelverarbeitung :
echo ----------------------
echo.
echo Verarbeite 1test_ok.rar...
%WinRarExec% -idc x 1test_ok.rar .\Einzelverarbeitung\1test_ok\

echo ---
echo Errorlevel: %ERRORLEVEL%
echo ---
if %ERRORLEVEL% EQU 0 (echo Kein Fehler
                       echo weiterverarbeitung, del Datei)
if %ERRORLEVEL% NEQ 0 (echo Fehler, Datei wird nicht geloescht)
echo.
echo Verarbeite 2test_fehler.rar...
%WinRarExec% -idc x 2test_fehler.rar .\Einzelverarbeitung\2test_fehler\

echo ---
echo Errorlevel: %ERRORLEVEL%
echo ---
echo.
if %ERRORLEVEL% EQU 0 (echo Kein Fehler
                       echo weiterverarbeitung, del Datei)
if %ERRORLEVEL% NEQ 0 (echo Fehler, Datei wird nicht geloescht)
echo.
echo ----------------
echo : for-Schleife :
echo ----------------
echo.
for /f %%i in ('dir /b *.rar') do (  
	echo Verarbeite %%i...
	%WinRarExec% -idc x %%i .\Schleife\%%~ni\

	echo ---
	echo Errorlevel: %ERRORLEVEL%
	echo ---
	if %ERRORLEVEL% EQU 0 (echo Kein Fehler
                               echo weiterverarbeitung, del %%i)
	if %ERRORLEVEL% NEQ 0 (echo Fehler, Datei wird nicht geloescht)
	echo.
)
pause
Und hier die Ausgabe bei der Ausführung:
----------------------
: Einzelverarbeitung :
----------------------

Verarbeite 1test_ok.rar...


Extracting from 1test_ok.rar

Creating    .\Einzelverarbeitung                                            OK
Creating    .\Einzelverarbeitung\1test_ok                             OK
Extracting  .\Einzelverarbeitung\1test_ok\test.txt                OK
All OK
---
Errorlevel: 0
---
Kein Fehler
weiterverarbeitung, del Datei

Verarbeite 2test_fehler.rar...


Extracting from 2test_fehler.rar

Creating    .\Einzelverarbeitung\2test_fehler                        OK
Extracting  .\Einzelverarbeitung\2test_fehler\test.txt           99%
test.txt             - CRC failed
Unexpected end of archive
Total errors: 2
---
Errorlevel: 3
---

Fehler, Datei wird nicht geloescht

----------------
: for-Schleife :
----------------

Verarbeite 1test_ok.rar...


Extracting from 1test_ok.rar

Creating    .\Schleife                                                               OK
Creating    .\Schleife\1test_ok                                                OK
Extracting  .\Schleife\1test_ok\test.txt                                   OK
All OK
---
Errorlevel: 3
---
Fehler, Datei wird nicht geloescht

Verarbeite 2test_fehler.rar...


Extracting from 2test_fehler.rar

Creating    .\Schleife\2test_fehler                                          OK
Extracting  .\Schleife\2test_fehler\test.txt                             99%
test.txt             - CRC failed
Unexpected end of archive
Total errors: 2
---
Errorlevel: 3
---
Fehler, Datei wird nicht geloescht

Drücken Sie eine beliebige Taste . . .
Wie man sehen kann, funktioniert bei der Einzelverarbeitung alles wie gewünscht, dir rar.exe (Kommandozeilentool von Winrar) setzt bei der fehlerfreien .rar-Datei den Errorlevel auf 0, bei der fehlerhaften auf 3 (was laut der Winrar Hilfe auch OK ist).
Beim ersten durchlauf der Schleife wird wieder die fehlerfreie .rar-Datei verarbeitet, der Errorlevel bleibt allerdings auf 3, wie auch beim zweiten Schleifendurchlauf. Es sieht also so aus, als wird der Errorlevel in der Schleife nicht verändert.
Ich bin ziemlich ratlos, kann mir jemand weiterhelfen? Wäre sehr dankbar!

Content-Key: 34983

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

Ausgedruckt am: 28.03.2024 um 12:03 Uhr

Mitglied: Biber
Biber 28.06.2006 um 09:33:23 Uhr
Goto Top
Moin Bierfreund,

ist eine Art optischer Täuschung, der Du aufgesessen bist.

Diese Sequenz...
...
echo.
for /f %%i in ('dir /b *.rar') do (  
    echo Verarbeite %%i...
    %WinRarExec% -idc x %%i .\Schleife\%%~ni
    echo ---
    echo Errorlevel: %ERRORLEVEL%
    echo ---
    if %ERRORLEVEL% EQU 0 (echo Kein Fehler
                               echo weiterverarbeitung, del %%i)
    if %ERRORLEVEL% NEQ 0 (echo Fehler, Datei wird nicht geloescht)
    echo.
)
....
..ist, auch wenn es anders formatiert ist, für den CMD-Interpreter eine Zeile.
Und die dort enthaltenen Variablen werden einmal aufgelöst.
So auch %ErrorLevel%.

Suche mal im Forum nach DelayedExpansion oder "verzögerter Variablenauflösung".

Abhilfe:
...
echo.
Setlocal EnableDelayedExpansion
for /f %%i in ('dir /b *.rar') do (  
    echo Verarbeite %%i...
    %WinRarExec% -idc x %%i .\Schleife\%%~ni
    echo ---
    echo Errorlevel: !ERRORLEVEL!
    echo ---
    if !ERRORLEVEL! EQU 0 (echo Kein Fehler
                               echo weiterverarbeitung, del %%i)
    if !ERRORLEVEL! NEQ 0 (echo Fehler, Datei wird nicht geloescht)
    echo.
)
..

Grüße
Biber
Mitglied: Bierfreund
Bierfreund 28.06.2006 um 13:56:44 Uhr
Goto Top
OK, Danke funktioniert super!
Bin zwar aus den anderen Beiträgen im Forum auch nicht so richtig schlau geworden, was dieses "setlocal EnableDelayedExpansion" genau macht, aber Hauptsache es funktioniert erstmal!
Mitglied: Bierfreund
Bierfreund 28.06.2006 um 14:27:06 Uhr
Goto Top
Also, mich hat das ganze nicht in Ruhe gelassen, ich verwende einfach nicht gerne etwas, dass ich nicht verstanden habe. In der Hilfe von set (set /?) habe ich eine Erklärung gefunden, die ich ziemlich gut finde, jetzt verstehe ich es auch. Ich poste es deshalb mal:
Die verzögerte Erweiterung von Variablen verbessert die Möglichkeiten der
Variablenerweiterung. Bisher wurden die Variablen beim Lesen des Texts, und
nicht bei dessen Ausführung, erweitert. Das folgende Beispiel zeigt ein
Problem, das dabei auftritt:

    set VAR=vorher
    if "%VAR%" == "vorher" (  
        set VAR=nachher;
        if "%VAR%" == "nachher" @echo Es funktioniert!  
    )

Die Meldung würde nie angezeigt, weil %VAR% in beiden IF-Befehlen
beim Lesen des ersten IF-Befehls erweitert wird, weil es logisch zu diesem
gehört. Daher vergleicht der zweite IF-Befehl "vorher" mit "nachher" was nie  
gleich sein kann. Auch das folgende Beispiel funktioniert nicht wie erwartet:

    set LISTE=
    for %i in (*) do set LISTE=%LISTE% %i
    echo %LISTE%

Es wird KEINE Liste der Dateien im aktuellen Verzeichnis erstellt, stattdessen
erhält LISTE den Namen der letzten Datei als Wert. Dies ist der Fall, weil
%LISTE% nur einmal beim Lesen des IF-Befehls erweitert wird. Zu diesem
Zeitpunkt ist LISTE leer.
Die FOR-Schleife, die tatsächlich ausgeführt wird, lautet:

    for %i in (*) do set LISTE= %i

Hiermit wird der Variablen LISTE immer wieder der letzte Dateiname
zugewiesen.

Die verzögerte Erweiterung von Umgebungsvariablen erlaubt es, eine
Umgebungsvariable, unter Verwendung eines weiteren Zeichens (dem
Ausrufezeichen), zur Laufzeit zu erweitern. Mit aktivierter verzögerter
Erweiterung von Umgebungsvariablen können obige Beispiele wie folgt geschrieben
werden:

    set VAR=vorher
    if "%VAR%" == "vorher" (  
        set VAR=nachher
        if "!VAR!" == "nachher" @echo Es funktioniert!  
    )

    set LISTE=
    for %i in (*) do set LISTE=!LISTE! %i
    echo %LISTE%

Wenn die Befehlserweiterungen aktiviert sind, gibt es mehrere dynamische
Umgebungsvariablen, die zwar erweiterungsfähig sind, aber nicht in der Liste
von Variablen auftauchen, die mit SET angezeigt werden. Diese Variablenwerte
werden bei jeder Werterweiterung der Variable dynamisch berechnet. Falls eine
Variable mit einem dieser Namen definiert wird, dann überschreibt diese
Definition die unten stehende dynamische Definition:

%CD% - expandiert zum aktuellen Verzeichnisnamen.

%DATE% - expandiert zum aktuellen Datum unter Verwendung desselben Formats
    wie der DATE-Befehl.

%TIME% - expandiert zur aktuellen Zeit unter Verwendung desselben Formats
    wie der TIME-Befehl.

%RANDOM% - expandiert zu einer zufällig gewählten Dezimalzahl
    zwischen 0 und 32767.

%ERRORLEVEL% - expandiert zum aktuellen ERRORLEVEL-Wert.

%CMDEXTVERSION% - expandiert zur Versionsnummer der aktuellen Erweiterungen
    für den Befehlsinterpreter.

%CMDCMDLINE% - expandiert zur ursprünglichen Befehlszeile, die den
    Befehlsinterpreter aufgerufen hat.

Allerdings hätte ich auch gleich nochmal eine Frage:
Um die DelayedExpansion zu aktivieren gibt es mehrere Möglichkeiten:
1. Durch die Zeile "setlocal EnableDelayedExpansion" im Batch
2. Permanent in der Registry durch setzen des Keys "DelayedExpansion" REG_DWORD 0x1 unter HKEY_CURRENT_USER\Software\Microsoft\Command Processor bzw. HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor
3. Durch Aufrufen von cmd.exe mit dem Schalter /V:On

Ich arbeite sehr oft mit cmd.exe /u damit ist es möglich bei Umleitungen in Dateien Umlaute zu erhalten (zb. bei Umleitung von dir, dass Dateien mit Umlauten enthält). cmd.exe /u bewirkt die Ausgabe interner Befehle in eine Pipe oder Datei im UNICODE-Format.
Gibt es eine Möglichkeit die Verwendung des UNICODE-Formats durch cmd.exe auch permanent über die Registry bzw eine Zeile im Batch zu aktivieren?
Mitglied: Biber
Biber 28.06.2006 um 20:59:17 Uhr
Goto Top
Moin Bierfreund,

erstmal die offene Frage (UNICODE-Output per RegKey einstellen): Nein, geht nicht/gibt es nicht. face-sad

Und noch eine Anmerkung zur M$-Hilfe, die ich auch relativ gut finde:

Zwei Schmunzelfehler sind gerade in den beiden "Set VAR=vorher/nachher"-Beispielen.

a) Im ersten Beispiel hat der Verfasser des Textes ganz in Gedanken ein Semikolon angehängt:
set VAR=vorher
    if "%VAR%" == "vorher" (  
        set VAR=nachher;
        if "%VAR%" == "nachher" @echo Es funktioniert!  
    )
... die Variable %VAR% hat dann auch den Wert "nachher;" (in der Zeile nach dem Klammer-Zu natürlich erst)
Hier war der Autor gedanklich wohl noch bei der Java -Programmierung - wo das doch so pfuipfui behandelt wurde im offiziellen M$-Umfeld

b) der zweite Schmunzelbug ist dann, wenn ihr den Code unten mal laufen lasst...
@echo off & Setlocal EnableDelayedExpansion
    set VAR=vorher
    if "%VAR%" == "vorher" (  
        set VAR=nachher
        if "!VAR!" == "nachher" @echo Es funktioniert!  
    )
Ausgabe ist ..."Es funktioniert" (ohne Ausrufungszeichen!) ... weil M$ leider vergessen hat, dass nicht immer auf ein Ausrufungszeichen eine [Zitat] "verzögert erweiterte Variable" folgt.

Zum Brüllen ist es, wenn die gut gewollte Zeile so eingetippselt worden wäre:
if "%VAR%" == "nachher" @echo !Es funktioniert!
Kaum zu glauben, aber dann ist der Output:
ECHO ist eingeschaltet (ON).
*SichVornKoppKlatscht*

Na ja... Bill Gates ist trotzdem Millardär geworden.. entweder liegt es am Marketing oder an den Personaleinsparungen bei Qualitätssicherung und MSKB-Übersetzungen..

Gruß
Biber