if-statementbatch-file

If defined var fails to prevent syntax error from sending output to an undefined var


Consider the following snippet of Batch Scripting. . .

The goal is to write output to 2 files if log is defined (a log file) - or to use arg 2 only (another log file). I have successfully used this syntax in the past, (at least - from what I recall) but for some reason, this continuously fails and gives me the error output posted below the code. What silly thing am I missing today?

@Echo Off

Setlocal EnableDelayedExpansion EnableExtensions
 If defined log (
   Echo Log is defined.
   If not "%~4"=="Yes" (
     If "%~nx2"=="%logNam%" (
       <nul (set /p "lineout=!WO_Log1!!cr!!lf!")>>%log%
     ) else (
       <nul (set /p "lineout=!WO_Log1!!cr!!lf!")>>%log%
       <nul (set /p "lineout=!WO_Arg1!!cr!!lf!")>>"%~2"
     )
   ) else (
     >>%log% Echo(!WO_Log1!
     >>"%~2" Echo(!WO_Arg1!
   )
 ) else (
   Echo Log is NOT defined.
   Echo "%~2"
   If not "%~4"=="Yes" (
     <nul (set /p "lineout=!WO_Log1!!cr!!lf!")>>"%~2"
   ) else (
     2>&1 >>"%~2" Echo(!WO_Log1!
   )
 )
The syntax of the command is incorrect.

C:\Users\foobar>       <nul (set /p "lineout=!WO_Log1!!cr!!lf!")>>

Am I mistaken, or should this line never have evaluated if the var log was never defined? I have confirmed that removing any reference to %log% solves the problem, but it seems like it should NOT be an issue. . . Do I need to first check for the inverse, and make the first condition as if NOT defined log instead?


Solution

  • I believe you should continue with your hazadous guesses.

    I modified your original code to

     If "%~nx2"=="%logNam%" (
       <nul (set /p "lineout=!WOaLog1!!cr!!lf!")>>%log%
     ) else (
       <nul (set /p "lineout=!WObLog1!!cr!!lf!")>>%log%
    

    Note WOaLog1, WObLog1 - and then c, etc for similar lines. This allowed me to determine which of the lines was generating the syntax error (and yes, surely the nature of the error could be displayed but isn't)

    Target : WOaLog1

    The parser would scan this line and replace any %var% with the value of that variable when the for is encountered. At that time, %log% is not set, or empty, so the parser sees

    <nul (set /p "lineout=!WOaLog1!!cr!!lf!")>>
    

    notices that there is no destination specified for the redirection and declares a syntax error (Microsoft:guess where...!)

    Replace the %log% with "%log%" and re-run.

    Target : WObLog1

    Because the destination is now "", which may be non-sensical, but isn't empty.

    Naturally, !var! is not PARSED as an empty string, since it may or may not be assigned at RUN-TIME.

    So, as a matter of course, I'd always specify a redirect-to-file as quoted so that "Spaces in filenames can be.accommodated"

    and I follow the mantra that the !var! form should only be used within a code block where var is being varied within that block.