Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
140 views
in Technique[技术] by (71.8m points)

windows - Writing output and error of a command to separate variables for Log File+Console

Following the post: https://stackoverflow.com/a/34489424/14947713 where @dbenham posted his code: Where he is able to Redirect Stdout/Stderr to variables and designs an early version that utilizes a file which is more efficient as he claims.

What I am not able to figure out is how to replace his "yourCommand" with a :call to a piece of code lower in the same script (ffmpeg processes & For loops). In the end I am trying to control what appears on the console but to thoroughly record what happens in a log file.

I've been searching and comparing/testing scripts for days but can't seem to break through this. The bottom piece of code is the ffmpeg script with it's existing logging function which I am aiming to recreate/reutilize within this @dbenham script.

@echo off
setlocal disableDelayedExpansion
set "STDOUT="
SET "STDERR="
for /f "delims=" %%E in (
   '2^>^&1 (for /f "delims=" %%O in ('^
      yourCommand^
   ^^^^^^^| findstr /n /r "^"'^) do @(echo ^^^^^^^|%%O^)^) ^| findstr /n /r "^"'
) do (
   set "ln=%%E"
   setlocal enableDelayedExpansion
   set "ln=x!ln:*:=!"
   set "ln=!ln:=s!"
   if "!ln:~0,2!"=="x|" (
      set "ln=!ln:~0,-1!"
      for /f "delims=" %%A in (^""!STDOUT!"^") do for /f "delims=" %%B in (^""!ln:*:=!"^") do (
        endlocal
        set "STDOUT=%%~A%%~B
"
      )
   ) else (
      for /f "delims=" %%A in (^""!STDERR!"^") do for /f "delims=" %%B in (^""!ln:~1!"^") do (
        endlocal
        set "STDERR=%%~A%%~B
"
      )
   )
)
setlocal enableDelayedExpansion
for %%L in (^"^
%= empty line =%
^") do (
  if defined STDOUT (
    set "STDOUT=!STDOUT:
=%%~L!"
    set "STDOUT=!STDOUT:s=!"
    set "STDOUT=!STDOUT:~0,-1!"
  )
  if defined stderr (
    set "STDERR=!STDERR:
=%%~L!"
    set "STDERR=!STDERR:s=!"
    set "STDERR=!STDERR:~0,-1!"
  )
)

echo ** STDOUT **
echo(!STDOUT!
echo ** STDERR **
echo(!STDERR!
exit /b

I have modified the above code as such for easier testing purposes: @echo off setlocal disableDelayedExpansion set /a out.cnt=err.cnt=0

(for /f "delims=. tokens=1*" %%A in ('^""%~f0" :test5 2^>err.log ^| findstr /n "^"^"') do (
    for /f "delims=:" %%N in ("%%A") do (
        set "ln=%%A"
        echo this is the ln var: "%ln%"
        setlocal enableDelayedExpansion
        for /f "delims=" %%B in (^""!ln:*:=!"^") do (
            endlocal
            set "out.%%N=%%~B"
            set "out.cnt=%%N"
        )
    )
)
)2>err.log
for /f "delims=" %%A in ('findstr /n "^" err.log') do for /f "delims=:" %%N in ("%%A") do (
  set "ln=%%A"
  echo this is the ln2 var: "%ln%"
  setlocal enableDelayedExpansion
  for /f "delims=" %%B in (^""!ln:*:=!"^") do (
    endlocal
    set "err.%%N=%%~B"
    set "err.cnt=%%N"
  )
)

:: Display the results
setlocal enableDelayedExpansion
echo ** STDOUT **
for /l %%N in (1 1 %out.cnt%) do echo(!out.%%N!
echo ** STDERR **
for /l %%N in (1 1 %err.cnt%) do echo(!err.%%N!
echo ** STDERR END **
exit /b


:test5
echo - This is the TEST5
    echo STDOUT line 1 with empty line following
    echo(
>&2 echo STDERR line 1 with empty line following
>&2 echo(
    echo STDOUT line 3 with poison characters "(<^&|!%%>)" (^<^^^&^|!%%^>)
>&2 echo STDERR line 3 with poison characters "(<^&|!%%>)" (^<^^^&^|!%%^>)
    echo err.4:STDOUT line 4 spoofed as stderr - No problem!
>&2 echo out.4:STDERR line 4 spoofed as stdout - No problem!
    echo :STDOUT line 5 leading colon preserved
>&2 echo :STDERR line 5 leading colon preserved
    echo ;STDOUT line 6 default EOL of ; not a problem
>&2 echo ;STDERR line 6 default EOL of ; not a problem
exit /b

I came across this script(below here): https://stackoverflow.com/a/9344547/14947713 but it is beyond-me for the moment on how I can re-configure to use. @echo off setlocal if "%~1" neq "" goto :test

:: Initialize
set log="myLog.log"
2>nul del %log%
2>nul del "test*.marker"
set procCount=5
set testCount=10

:: Launch %procCount% processes that write to the same log
for /l %%n in (1 1 %procCount%) do start "" /b "%~f0" %%n

:wait for child processes to finish
2>nul dir /b "test*.marker" | find /c "test" | >nul findstr /x "%procCount%" || goto :wait

:: Verify log results
for /l %%n in (1 1 %procCount%) do (
  <nul set /p "=Proc %%n log count = "
  find /c "Proc %%n: " <%log%
)

:: Cleanup
del "test*.marker"
exit /b

==============================================================================
:: code below is the process that writes to the log file

:test
set instance=%1
for /l %%n in (1 1 %testCount%) do (
  call :log echo Proc %instance% says hello!
  call :log dir "%~f0"
)
echo done >"test%1.marker"
exit

:log command args...
2>nul (
  >>%log% (
    echo ***********************************************************
    echo Proc %instance%: %date% %time%
    %*
    (call ) %= This odd syntax guarantees the inner block ends with success  =%
            %= We only want to loop back and try again if redirection failed =%
  )
) || goto :log
exit /b

The existing ffmpeg script with it's existing logging which 1st: Sets up the logging structure to the %drive% destination (contains "!"), creates the new logging destination directory(s) and saves the filename as the date+time.

2nd(core-1): Uses ffprobe.exe to search for define audio codecs (i.e. "dts") 3rd(core-2): Each result is then fed to ffmpeg to copy the file but to transcode to "eac3" & "ac3".

Disclosure:

  1. Existing Problems with this ffmpeg script include the "FilesEncoded" count. Ideally it would show the count

  2. I am also trying to incorporate "start /abovenormal" so I can have the ffmpeg processes a high priority.

  3. I seem to be stuck, but I have spent yesterday looking to use ffmpeg-progressbar-cli https://github.com/sidneys/ffmpeg-progressbar-cli so it would show a per-file progress bar, and basic information, which is why there is a 2nd FINALCOMMAND line ::out at the end. But no luck....

I appreciate any help anyone can provide.

@ECHO OFF
rem #######NEEDED INSTALLED####################################
rem For the "ffmpeg-bar wrapper" node.js is needed
rem And then npm install --global ffmpeg-progressbar-cli
rem #######NEEDED INSTALLED####################################
setlocal
rem #######1-Destination Drive #############
SET drive=T:4k.temp
set string=%CD%
rem ####1-Destination Drive###################################
setlocal EnableDelayedExpansion
    set "SEARCHSlash="
    set "REPLACETEXT=_"
set "modified="
set "OUTTEXTFILE="
for %%* in (.) do SET LogFolder=%%~n*
set "LOGFILE="
set "SEARCHDrive="
set "REPLACEDriveLetter="
set "timestmpIN="
set "timestmpFIN="
SET "DT="
SET "HH="&SET "MM="&SET "SS="&SET "timestamp1="
SET "daymth="
set "colon=^:"
set "period=^."
    set "modified=!string:%SEARCHSlash%=%REPLACETEXT%!"
    ECHO !modified!
    set "SEARCHDrive=!modified:~0,18!"
    set "OUTTEXTFILE=!modified:%SEARCHDrive%=%REPLACEDriveLetter%!"
        SET DT=%date:/=-%
        SET daymth=%DT:~4,5%
        for /F "tokens=2" %%i in ('date /t') do set mydate=%%i
        set mytime=%time%
        ECHO Current time is %mydate%:%mytime%
        FOR /F "TOKENS=1 DELIMS=:" %%A IN ('TIME/T') DO SET HH=%%A
        SET MM=%time:~3,2%&SET SS=%time:~6,2%
        SET "timestamp1=%HH%.%MM%.%SS%"
        ECHO This is timestamp:             %timestamp1%
rem #######2-Destination Logs #############
    MD "%drive%Logs\%LogFolder%"
    SET LOGFILE=%drive%Logs\%LogFolder%Log-%OUTTEXTFILE%--%daymth%..%timestamp1%.log
    (call ^:logit)>>%LOGFILE%
    ECHO This is the logfile:                   %LOGFILE%
rem #######2-Destination Logs #############
ECHO THIS IS THE START OF LOGIT
endlocal
:logit
setlocal EnableExtensions EnableDelayedExpansion
SET "FINALCOMMAND="
rem #######3-Codecs Desired to Convert #############
SET "Codec1=dts"
SET "Codec2=null2"
SET "Codec3=null2"
rem #######3-Codecs Desired to Convert #############
    setlocal EnableExtensions DisableDelayedExpansion
    SET "ProgramFolder=C:Program FilesFFmpeg-v2020in"
    SET "ProbeOptions=-v quiet -select_streams a:0 -show_entries "stream^^=codec_name" -of json"
set "FilesFound=0"
set "FilesEncoded=0"
set "FullFileName="
set "output="
ECHO This is the Current Directory:             %CD%
ECHO Loop1Loop1Loop1Loop1Loop1Loop1Loop1Loop1Loop1Loop1Loop1Loop1Loop1Loop1Loop1Loop1Loop1Loop1Loop1Loop1
for /F "delims=" %%I in ('dir *.mkv *.mp4 /A-D-H /B /S 2^>nul') do (
    ECHO This is the Program Folder: %ProgramFolder%
    ECHO This is the Program Options: %ProgramOptions%
    set "FullFileName=%%I"
    ECHO "FullFileName %%I"
    set "output=%drive%%%~pI%%~nxI"
        SET "folderOUTpath2=%drive%%%~pI"
        ECHO This is the Folderoutpath2: "%folderOUTpath2%"
        SET "folderOUTpath=%folderOUTpath2%"
    ECHO "folderOUTpath-nonVar: %drive%%%~pI"
    ECHO "folderOUTpath-1       %folderOUTpath%"

    set /A FilesFound+=1
    set "AudioCodec="
    SET "SkipCodecs="
    ECHO FullFileName2-nonVar       "FullFileName %%I"
    ECHO FullFileName2              "%FullFileName%"
    ECHO folderOUTpath2-nonVar      "folderOUTpath %drive%%%~pI"
    ECHO folderOUTpath2-orig:       %folderOUTpath%
    ECHO folderOUTpath2             !folderOUTpath2!
        ECHO folderOUTpath2-orig:       %folderOUTpath%
    ECHO Loop2Loop2Loop2Loop2Loop2Loop2Loop2Loop2Loop2Loop2Loop2Loop2Loop2Loop2Loop2Loop2Loop2
    ECHO this is variable           %%B
            ECHO this is variable   %%~B
            ECHO this is variable   %%C
            ECHO this is variable   %%~C

    for /F "eol={ tokens=1,2 delims=,:[ ]{} " %%B in ('""%ProgramFolder%ffprobe.exe" %ProbeOptions% "%%I""') do (

            ECHO this is variable   %%B
            ECHO this is variable   %%~B
            ECHO this is variable   %%C
            ECHO this is variable   %%~C
            if "%%~B" == "codec_name" (
                if not defined AudioCodec (
                    set &qu

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
Waitting for answers

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...