3

Is there any standard/encouraged Windows batch file coding style?

I would think that if I want my batch files to be easy to read/mantain, I should care about this, but searching the web I found very little about it, and I didn't get any reviews (not even comments) on this Code Review question, so it makes me wonder if this is something I shouldn't care much about...

  • Are you talking abuout Linux/Unix scripts? – Tulains Córdova Aug 24 '16 at 11:37
  • @TulainsCórdova Windows batch files. I just edited the question to make it clear. – carlossierra Aug 24 '16 at 11:48
  • @carlossierra I opened a bounty on it over on code review. – RubberDuck Aug 25 '16 at 2:05
  • @RubberDuck did you see my own answer over there? Since I didn't get much feedback here nor there, I decided to make my own proposal. Let me know what you think about it. – carlossierra Aug 25 '16 at 2:08
  • 1
    @RubberDuck thanks for starting the bounty. I appreciate it!! – carlossierra Aug 25 '16 at 2:09
4
  • Naming, the file the variables, the functions.
  • Comments, what the script do, what that complicated portion of code do.
  • Isolate portion of code in functions
  • Consistency in the coding style, whatever you choose.

These are what makes code really maintenable whatever kind of code it is. Now batches are supposed to be quite short code and not so much files, so that's probably why there isn't that much about coding standard and so on.

If you have really a lot of batches, a documentation outside showing how they work together would proabably be needed.

To be honest i'm not used to batch, so i don't get everything about the syntax you use in your code review's post. But your works seems pretty fine to me, maybe people just didn't comment "i don't see anything wrong here".

  • Thanks for your suggestions and the positive comments about what you saw on my Code Review post. Encouraged by that, I took your ideas and mixed them with some ideas of mine to come up with a proposal that I just posted on the Code Review question. – carlossierra Aug 25 '16 at 2:25
2

When I am writing batch files, they usually rely on the following template:

@title Optional Title
@echo off
setlocal EnableExtensions DisableDelayedExpansion

::Comment that describes purpose and usage of the script; this should also
::contain (original) script name, version, date and author, if applicable.

rem Define global constants (read-only variables) here (names begin with `_`).

rem Initialise global variables (those accessed also by sub-routines) here,
rem if any (names begin with `$`).

rem Parse command line arguments and/or user input data here;
rem regard cases when too few or too many arguments are provided;
rem regard cases when user input is empty.

rem Place code for processing here:
rem In general, avoid non-ASCII characters within functional code;
rem use lower-case (for commands, sub-commands, verbs and keywords);
rem use upper-case only for switches, variable names and `for` references;
rem place single space between commands, switches and arguments;
rem place single spaces around redirection operators too;
rem avoid excessive line concatenation (by `&`);
rem insert explanatory comments using the `rem` command.
(
    rem Indent parenthesised blocks.
)

rem Return resulting output here.

endlocal
exit /B


:SUB  rtn_return  ref_variable  val_value
    setlocal DisableDelayedExpansion
    ::Comment that describes purpose and usage of the sub-routine;
    ::include the meanings of the aforementioned arguments (like:
    ::`rtn_*` denote return values, so they hold variable names;
    ::`ref_*` denote references, so they hold variable names too;
    ::`val_*` denote values, so they hold immediate values).

    rem Define local constants here (names begin with `_`).

    rem Parse arguments here; check whether too few/many arguments are given;

    rem Place code for processing here.

    rem Return resulting output here; regard the `endlocal` barrier
    rem (for `rtn_*` arguments, whose values need to survive it).

    endlocal
    exit /B

If a help system (support for /? switch) is about to be implemented, I usually use this template:

@title Optional Title
@echo off
setlocal EnableExtensions DisableDelayedExpansion

::Comment that describes purpose and usage of the script; this should also
::contain (original) script name, version, date and author, if applicable.

::::
::::"%~nx0"  [version 0.0]
::::
::::Help message text that describes the purpose of the script in detail;
::::some parts of that text may be placed elsewhere in the script.
::::The continued text could describe the exact usage of the script,
::::illustrating the syntax and listing all the accepted parameters.
::::

rem Define global constants (read-only variables) here (names begin with `_`).

rem Initialise global variables (those accessed also by sub-routines) here,
rem if any (names begin with `$`).

rem Parse command line arguments and/or user input data here;
rem regard cases when too few or too many arguments are provided;
rem regard cases when user input is empty.
if "%~1"=="/?" call :HLP & exit /B

rem Place code for processing here:
rem In general, avoid non-ASCII characters within functional code;
rem use lower-case (for commands, sub-commands, verbs and keywords);
rem use upper-case only for switches, variable names and `for` references;
rem place single space between commands, switches and arguments;
rem place single spaces around redirection operators too;
rem avoid excessive line concatenation (by `&`);
rem insert explanatory comments using the `rem` command.
(
    rem Indent parenthesised blocks.
)

rem Return resulting output here.

endlocal
exit /B


:SUB  rtn_return  ref_variable  val_value
    setlocal DisableDelayedExpansion
    ::Comment that describes purpose and usage of the sub-routine;
    ::include the meanings of the aforementioned arguments (like:
    ::`rtn_*` denote return values, so they hold variable names;
    ::`ref_*` denote references, so they hold variable names too;
    ::`val_*` denote values, so they hold immediate values).

    rem Define local constants here (names begin with `_`).

    rem Parse arguments here; check whether too few/many arguments are given;

    rem Place code for processing here.

    rem Return resulting output here; regard the `endlocal` barrier
    rem (for `rtn_*` arguments, whose values need to survive it).

    endlocal
    exit /B


:HLP
    setlocal DisableDelayedExpansion
    for /F "delims=" %%H in ('findstr /B /L "::::" "%~f0"') do (
        call set "LINE=%%H"
        setlocal EnableDelayedExpansion
        echo(!LINE:*::::=!
        endlocal
    )
    endlocal
    exit /B


::::
::::  USAGE:
::::
::::    %~nx0 [/optional] [/switch] {/alternative | /switches} parameter
::::
::::    /optional    optional switch
::::    /switch      optional switch
::::    /alternative alternative switch
::::    /switches    alternative switch
::::    parameter    required parameter
::::

Check out all the comments which hold the most important coding style recommendations.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.