kriegstreiber
Goto Top

Batch FOR Schleife - Operationen aus CALL Befehl werden nicht ausgeführt

Hallo liebe Community ich habe ein Problem und komme nicht auf die Lösung. Also was habe ich vor, ich werkel an einem Skript, das mir *.mkv Dateien scannt und Anhand der Scanergebnisse am Ende umbenennt. Das soll sowohl mit Einzelfiles, als auch mit mehreren Files im Verzeichnis gehen. Nun ist es so, dass das Script mit Einzelfiles 100%ig funktioniert, mit Ordnerstrukturen die Variablen aus der Funktion CHECK aber nicht übernimmt. Auszüge aus dem Script:

rem --- Hardcoded settings. Cannot be changed ---
set "INPUTFILE=%~dpnx1"  
set "INPUTFILEPATH=%~dp1"  
set "INPUTFILENAME=%~n1"  
set "INPUTFILEEXT=%~x1"  
set "DIRFOUND=FALSE"  
set "FAKEP5ALLOWED=FALSE"  
set "FAKEP5=NO"  
set "TMP_FOLDER=SAME AS SOURCE"  
set "TARGET_FOLDER=SAME AS SOURCE"  
set "MKVTOOLNIX_FOLDER=INCLUDED"  
set "HDR_Info=No HDR Infos found"  
set "RESOLUTION=N/A"  
set "HDR=N/A"  
set "CODEC_NAME=N/A"  
set "FRAMERATE=N/A"  
set "FRAMES=N/A"  
set "DIR=FALSE"  
set /a ERRORCOUNT=0

rem Erkennen ob Verzeichnis oder Einzeldatei
dir /b/ad "%~1" >nul 2>nul && set DIRFOUND=TRUE  
if "!DIRFOUND!"=="TRUE" goto :MPREPARE  

rem Vorbereitungen fuer Massenumbenennung, setze Counter.
:MPREPARE
set "SOURCE_FOLDER=%~1"  
set /A SOURCEFILES=0 & set "SOURCEFILESC=0F"  
set /A FERRORCOUNT=0 & set "FERRORCOUNTC=0A"  
set /A DONECOUNT=0 & set "DONECOUNTC=08"  
set /A PFILECOUNT=0 & set "PFILECOUNTC=08"  
for /F %%i in ('dir "!SOURCE_FOLDER!\*.mkv" /B /A-d') do set /A SOURCEFILES=!SOURCEFILES!+1>nul  
goto :START

rem Start ist uninteressant, da kann ich nur noch ein paar Sachen einstellen, wie Reihenfolge der Variablen für die umbenennung und co. Wenn da alles ausgewählt ist und DIRFOUND=TRUE geht es zur Funktion MBEGIN.

rem Beginne Stapelverarbeitung für Verzeichnis.
:MBEGIN
if not exist "!TMP_FOLDER!" MD "!TMP_FOLDER!">nul  
if not exist "!TARGET_FOLDER!" MD "!TARGET_FOLDER!">nul  
for /F %%A in ('dir "!SOURCE_FOLDER!\*.mkv" /B /A-d') do (  
	set /A PFILECOUNT=!PFILECOUNT!+1
	set "INPUTFILE=%%A"  
	set "INPUTFILENAME=%%~nA"  
	set "INPUTFILEEXT=%%~xA"  
	call :CHECK
	echo.
	echo Filename   = [!INPUTFILENAME!]
	echo Video Info = [Resolution = !RESOLUTION!] [Codec = !CODEC_NAME!] [Frames = !FRAMES!] [FPS = !FRAMERATE!]
	echo HDR Info   = [!HDR_Info!]	
	pause
)

So ab hier ist jetzt das Problem, das bei "!RESOLUTION!" "!CODEC_NAME!" "!FRAMES!" "!FRAMERATE!" "!HDR_Info!" überall "N/A" angezeigt wird (also die Grundvariable die ich am Anfang festsetze. Die Variablen für die Datei (also die !INPUTFILE" Dinger) werden komischerweise übernommen. Alle Ergebnisse aus CHECK werden nicht übernommen. In CHECK sind auch Operationen drin die in einer FOR Schleife hängen, ich kopiere die Funktion CHECK am Ende auch nochmal rein. Die Funktion CHECK funktioniert soweit mit Einzeldateien tadellos, nur aus meiner Massenverarbeitung heraus irgendwie nicht. Woran könnte das liegen?

EDIT:
z.B dieser Befehl in CHECK:
"!MEDIAINFOpath!" --output=Video;%%HDR_Format_String%% "!INFOSTREAM!">"!TMP_FOLDER!\Info.txt"  
Erzeugt eine leere Info.txt. Bei einer Einzeldatei steht etwas drin. Auch wenn ich den Befehl mit echo wiedergebe ist die Variable !INFOSTREAM! korrekt gesetzt.

:CHECK
if not exist "!TMP_FOLDER!" MD "!TMP_FOLDER!">nul  
echo.
%CYAN%
echo Analysing File. Please wait...
echo.
set "INPUTSTREAM=!INPUTFILE!"  
set "INFOSTREAM=!INPUTFILE!"  
FOR /F "delims=" %%A in ('""!MEDIAINFOpath!" --output=General;%%VideoCount%% "!INFOSTREAM!""') do set "VIDEO_COUNT=%%A"  

::SET HDR FORMAT
"!MEDIAINFOpath!" --output=Video;%%HDR_Format_String%% "!INFOSTREAM!">"!TMP_FOLDER!\Info.txt"  
FOR /F "delims=" %%A IN ('findstr /C:"Dolby Vision" "!TMP_FOLDER!\Info.txt"') DO set "DVinput=YES"  
FOR /F "delims=" %%A IN ('findstr /C:"HDR10" "!TMP_FOLDER!\Info.txt"') DO set "HDRFormat=HDR10"  
FOR /F "delims=" %%A IN ('findstr /C:"HDR10+" "!TMP_FOLDER!\Info.txt"') DO set "HDRFormat=HDR10+"  
FOR /F "delims=" %%A IN ('findstr /C:"dvhe.05" "!TMP_FOLDER!\Info.txt"') DO set "HDRFormat=IPT-PQ-C2"  
FOR /F "delims=" %%A IN ('findstr /C:"HLG" "!TMP_FOLDER!\Info.txt"') DO set "HDRFormat=HLG"  

::SET DV FORMAT
"!MEDIAINFOpath!" --output=Video;%%HDR_Format_Profile%% "!INFOSTREAM!">"!TMP_FOLDER!\Info.txt"  
FOR /F "delims=" %%A IN ('findstr /C:".08" "!TMP_FOLDER!\Info.txt"') DO set "DVinput=YES" & set "DVprofile=8"  
FOR /F "delims=" %%A IN ('findstr /C:".07" "!TMP_FOLDER!\Info.txt"') DO set "DVinput=YES" & set "DVprofile=7"  
FOR /F "delims=" %%A IN ('findstr /C:".06" "!TMP_FOLDER!\Info.txt"') DO set "DVinput=YES" & set "DVprofile=6"  
FOR /F "delims=" %%A IN ('findstr /C:".05" "!TMP_FOLDER!\Info.txt"') DO set "DVinput=YES" & set "DVprofile=5"  
FOR /F "delims=" %%A IN ('findstr /C:".04" "!TMP_FOLDER!\Info.txt"') DO set "DVinput=YES" & set "DVprofile=4"  
FOR /F "delims=" %%A IN ('findstr /C:".03" "!TMP_FOLDER!\Info.txt"') DO set "DVinput=YES" & set "DVprofile=3"  

::DUAL LAYER OPERATION
if "!VIDEO_COUNT!"=="2" (  
	set "LAYERTYPE= DL"  
	set "DT=-map 0:1"  
	"!FFMPEGpath!" -loglevel panic -i "!INFOSTREAM!" -map 0:0 -c:v copy -to 1 "!TMP_FOLDER!\BL.mkv">nul 2>&1  
)
if "!DVinput!"=="YES" "!FFMPEGpath!" -loglevel panic -i "!INFOSTREAM!" !DT! -c:v copy -to 1 -bsf:v hevc_mp4toannexb -f hevc - | "!DO_VI_TOOLpath!" extract-rpu -o "!TMP_FOLDER!\RPU.bin" - >nul 2>&1  
if exist "!TMP_FOLDER!\BL.mkv" set "INFOSTREAM=!TMP_FOLDER!\BL.mkv"  

::BEGIN MEDIAINFO
FOR /F "delims=" %%A in ('""!MEDIAINFOpath!" --output=Video;%%Width%%x%%Height%% "!INFOSTREAM!""') do set "RESOLUTION=%%A"  
FOR /F "delims=" %%A in ('""!MEDIAINFOpath!" --output=Video;%%Format%%^-%%BitDepth%%Bit^-%%ColorSpace%%^-%%ChromaSubsampling%% "!INFOSTREAM!""') do set "CODEC_NAME=%%A"  
FOR /F "tokens=1,2 delims= " %%A in ('""!MEDIAINFOpath!" --output=Video;%%FrameRate_String%% "!INPUTSTREAM!""') do (  
	set "FRAMERATE=%%A"  
	set "FRAMERATE_ORIG=%%A"  
)
FOR /F "delims=" %%A in ('""!MEDIAINFOpath!" --output=Video;%%FrameCount%% "!INPUTSTREAM!""') do set "FRAMES=%%A"  
if "!VIDEO_COUNT!"=="2" set "FRAMES=N/A DL"  
if "!HDRFormat!"=="HDR10" (  
	set "HDR=TRUE"  
	%GREEN%
	echo HDR10 found.
)
if "!HDRFormat!"=="HLG" (  
	set "HDR=TRUE"  
	%GREEN%
	echo HLG found.
)
if "!HDRFormat!"=="HDR10+" (  
	set "HDR=TRUE"  
	set "HDR10P=TRUE"  
	%GREEN%
	echo HDR10+ Metadata found.
)
if "!DVprofile!"=="8" (  
	set "HDR=TRUE"  
	set "DV=TRUE"  
	set "DV_Profile=8"  
	%GREEN%
	echo Dolby Vision Profile 8 found.
)
if "!DVprofile!"=="7" (  
	set "HDR=TRUE"  
	set "DV=TRUE"  
	set "DV_Profile=7"  
	if "!RESOLUTION!"=="1920x1080" set "ELFILE=TRUE"  
	if exist "!TMP_FOLDER!\RPU.bin" (  
		FOR /F "usebackq" %%A IN ('!TMP_FOLDER!\RPU.bin') DO set "RPUSIZE=%%~zA">nul 2>&1  
		if "!RPUSIZE!" NEQ "0" (  
			"!DO_VI_TOOLpath!" info -s "!TMP_FOLDER!\RPU.bin">"!TMP_FOLDER!\RPUINFO.txt"  
			if exist "!TMP_FOLDER!\RPUINFO.txt" (  
				FOR /F "delims=" %%A IN ('findstr /C:"Profile:" "!TMP_FOLDER!\RPUINFO.txt"') DO set "subprofile=%%A"  
				if defined subprofile (
					for /F "tokens=3 delims=:/ " %%A in ("!subprofile!") do set "subprofile= %%A"  
				) else (
					set "subprofile="  
				)
			)
		)
	)
	%GREEN%
	if "!ELFILE!"=="FALSE" (  
		echo Dolby Vision Profile 7!subprofile!!LAYERTYPE! found.
	) else (
		echo Dolby Vision Profile 7!subprofile!!LAYERTYPE! EL Layer found.
	)
	set "DV_Profile=7!subprofile!!LAYERTYPE!"  
)
if "!DVprofile!"=="5" (  
	set "HDR=FALSE"  
	set "DV=TRUE"  
	set "DV_Profile=5"  
	%GREEN%
	echo Dolby Vision Profile 5 found.
)
if "!DVprofile!"=="4" (  
	set "HDR=TRUE"  
	set "DV=TRUE"  
	set "DV_Profile=4"  
	%GREEN%
	echo Dolby Vision Profile 4 found.
)
%GREEN%
if exist "!TMP_FOLDER!\Info.mkv" del "!TMP_FOLDER!\Info.mkv">nul  
if exist "!TMP_FOLDER!\BL.mkv" del "!TMP_FOLDER!\BL.mkv">nul  
if exist "!TMP_FOLDER!\RPU.bin" del "!TMP_FOLDER!\RPU.bin">nul  
if "!HDR!"=="TRUE" set "HDR_Info=!HDRFormat!"  
if "!HDR10P!"=="TRUE" set "HDR_Info=HDR10, !HDRFormat!"  
if "!DV!"=="TRUE" set "HDR_Info=Dolby Vision Profile !DV_Profile!"  
if "!HDR!!DV!"=="TRUETRUE" set "HDR_Info=!HDRFormat!, Dolby Vision Profile !DV_Profile!"  
if "!HDR10P!!DV!"=="TRUETRUE" set "HDR_Info=HDR10, !HDRFormat!, Dolby Vision Profile !DV_Profile!"  
echo.
echo Analysing complete.
if "!DIRFOUND!"=="TRUE" goto :eof  
if exist "!TMP_FOLDER!" RD /S /Q "!TMP_FOLDER!">nul  
TIMEOUT 3 /NOBREAK>nul
goto :START

Content-ID: 670655

Url: https://administrator.de/forum/batch-for-schleife-operationen-aus-call-befehl-werden-nicht-ausgefuehrt-670655.html

Ausgedruckt am: 19.02.2025 um 22:02 Uhr

Kriegstreiber
Lösung Kriegstreiber 12.01.2025 aktualisiert um 14:46:35 Uhr
Goto Top
So ich habe die Lösung gefunden, ich bin auch echt ein Depp ey. Der Fehler lag bereits in der Funktion :MBEGIN und ich habe nicht richtig geguckt :/ Das war die Ursache:

for /F %%A in ('dir "!SOURCE_FOLDER!\*.mkv" /B /A-d') do  

Natürlich wird bei dem Befehl der letzte Ordner "verschluckt". Ersetzt durch:

for %%A in ("!SOURCE_FOLDER!\*.mkv") do  

und schon geht auch alles. Achja, so als kleiner Tip was Verzeichnisvariablen angeht, wenn man z.B. Dateien hinzufügt.
Da ich viele Scripte erstelle wo ich Dateien/Verzeichnis mit set /p und Drag and Drop benutze, bzw. Scripte erstelle die mit Verzeichnissen/Dateien gestartet werden können (also z.B. MeinTool.cmd "C:\Meine Dateien\MeineDatei.txt") und man jetzt diesen Input als Variable anlegen will, kann man z.B set "MEIN_INPUT_FILE=%~1" nehmen. Das hat aber zur Folge, dass die Variable %MEIN_INPUT_FILE% in unserem Beispiel nun "C:\Meine Dateien\MeineDatei.txt" wäre. Bedeutet also dass die "" schon mit gesetzt sind. Da ich mir angewöhnt habe bei Verzeichnissen in den Scripts diese auch immer in "" zu setzen (sonst steigt Batch halt bei Leerzeichen und dergleichen aus) kam es oft zu dem Problem, das ich die Variable "%MEIN_INPUT_FILE%" gesetzt habe und nun das ganze oft nicht funktioniert, weil jetzt quasi ""C:\Meine Dateien\MeineDatei.txt"" verarbeitet wird. Um das zu verhindern habe ich mir angewöhnt, immer [%~dpnx1] (set "MEIN_INPUT_FILE=%~dpnx1") statt [%~1] (set "MEIN_INPUT_FILE=%~1") zu verwenden, weil hier die Variable keine "" hat und man wie gewohnt "%MEIN_INPUT_FILE%" nutzen kann. Vielleicht hilft es ja dem ein oder anderen.

Gruss an euch alle und schönen Sonntag gewünscht.
DivideByZero
DivideByZero 12.01.2025 um 14:55:17 Uhr
Goto Top
Moin,

danke, dass Du auch gleich die Lösung dargestellt hast. Aber der Code und Deine Überlegungen zeigen, warum es schwierig ist, Batch"code" zu debuggen und zu verstehen. Das, was Du machst, ist ideal für eine Programmiersprache oder die Powershell geeignet. Besser zu lesender und zu verstehender, kürzerer und weniger komplexer Code.

Gruß

DivideByZero
Kriegstreiber
Kriegstreiber 12.01.2025 aktualisiert um 15:59:32 Uhr
Goto Top
Leider kann ich nichts anderes als Batch, bin auch zu alt mich jetzt noch mit Powershell und Co. zu beschäftigen. Obwohl ich Batch jetzt nicht als Programmiersprache sehe, ist ja im Grunde nur eine Aneinanderreihung von CMD Befehlen. Komme noch aus der DOS Ära und da kann man ja dann zwangsweise Batch. Ich hatte mich mal an Free Pascal und der Lazarus IDE probiert, weil ich gerne viele meiner komplexeren Scripte in einer schönen GUI hätte, Häkchen setzen statt choice Befehle, aber bin auch daran kläglich gescheitert. Egal was ich probiere und übe ich "denke" immer in Batch und komm davon nicht los.
DivideByZero
DivideByZero 12.01.2025 um 16:11:06 Uhr
Goto Top
Wenn es für Dich und in der Sache funktioniert, ist es ja auch gut. Viele Wege führen nach Rom.

Schönen Sonntag,

DivideByZero
TK1987
TK1987 13.01.2025 um 00:16:46 Uhr
Goto Top
Moin,

Zitat von @Kriegstreiber:
rem Erkennen ob Verzeichnis oder Einzeldatei
dir /b/ad "%~1" >nul 2>nul && set DIRFOUND=TRUE  
if "!DIRFOUND!"=="TRUE" goto :MPREPARE  

rem Vorbereitungen fuer Massenumbenennung, setze Counter.
:MPREPARE
...
der Teil ergibt keinen Sinn.

Wenn er den Ordner gefunden hat, springt er zu :MPERPARE, welches die nächste Codezeile ist. Hat er den Ordner nicht gefunden, macht er aber genauso mit der nächsten Zeile weiter. Was genau wolltest du da tun?

Gruß Thomas
Kriegstreiber
Kriegstreiber 14.01.2025 aktualisiert um 16:32:41 Uhr
Goto Top
Das ist nur ein Auszug, das geht unten weiter.
Je nachdem ob Ordner oder Datei springt zu einer anderen Funktion.

dir /b/ad "%~1" >nul 2>nul && set DIRFOUND=TRUE  
if "!DIRFOUND!"=="TRUE" goto :MPREPARE  
if /i "%~x1"==".mkv" set "MKVExtract=TRUE" & goto CHECK  

goto :FALSEINPUT

So ist das normal, hatte den unteren Part nur weggelassen, weil die Verarbeitung von Einzeldateien ja einwandfrei funktionierte, nur bei der Massenverarbeitung hat er rumgespackt.
TK1987
TK1987 14.01.2025 um 17:04:53 Uhr
Goto Top
Zitat von @Kriegstreiber:
Das ist nur ein Auszug, das geht unten weiter.
Je nachdem ob Ordner oder Datei springt zu einer anderen Funktion.
na dann ist ja gut, hatte mich nur gewundert face-wink