Skip to content
FreeDOSDeep Dive Published Updated 7 min readViews unavailable

Writing Batch Files on FreeDOS

A FreeCOM-specific guide to portable DOS batch files using arguments, SHIFT, IF, ERRORLEVEL, FOR, GOTO, CALL, redirection, and defensive expansion.

FreeDOS batch files are command lists interpreted by FreeCOM, the project’s COMMAND.COM replacement. They support arguments, environment variables, redirection, pipes, IF, FOR, GOTO, SHIFT, and nested scripts through CALL. They are not Windows cmd.exe scripts: copying modern constructs such as SET /A, IF /I, NEQ, CALL :label, GOTO :EOF, or substring expansion into FreeCOM is not portable and may fail outright.

Start with a reversible command sequence

A .BAT file executes the same commands available at the interactive FreeCOM prompt. Begin with a script that reports what it intends to do and writes to a new destination rather than deleting or overwriting source data.

@ECHO OFF
ECHO Copying text files to C:\BACKUP
IF NOT EXIST C:\BACKUP\NUL MD C:\BACKUP
COPY *.TXT C:\BACKUP\
IF ERRORLEVEL 1 GOTO COPYERROR
ECHO Copy completed.
GOTO END

:COPYERROR
ECHO Copy failed. Original files were not deleted.

:END

@ suppresses echoing for one line; ECHO OFF suppresses subsequent command display. REM is the documented comment command. A leading colon defines a label when it begins the line. Do not use :: as if it were a formally supported comment syntax; other DOS shells and unusual parsing contexts can treat it differently.

The directory test uses C:\BACKUP\NUL, an established DOS compatibility pattern documented by FreeCOM: character devices appear virtually in a valid local directory, so testing for NUL can distinguish an existing path. It is not a universal test for remote filesystems or non-DOS shells.

Environment variables are text substitution

SET NAME=value writes text into the process environment, and %NAME% substitutes that text before FreeCOM parses the resulting command line.

SET DEST=C:\BACKUP
ECHO Destination is %DEST%

FreeCOM documents /C to preserve the variable name’s case, /I as a diagnostic for environment size, and /P to prompt for a value. It does not document the Windows arithmetic form SET /A. Use an external arithmetic utility, a purpose-built program, or another scripting language when arithmetic is a real requirement.

Expansion before parsing creates a security and correctness boundary. A variable containing redirection, pipes, unmatched quotes, or command words can reshape the line that executes. Do not insert untrusted filenames or user input into destructive commands. Quoting a normal argument helps with spaces, but classic DOS quoting is not a complete escaping language for every metacharacter.

SET /P ANSWER=Type YES to continue:
IF "%ANSWER%"=="YES" GOTO CONFIRMED
ECHO Cancelled.
GOTO END

:CONFIRMED
ECHO Confirmed, but no destructive action is performed here.
:END

The comparison is case-sensitive. FreeCOM’s documented IF syntax has no /I case-insensitive switch. If case folding is required, use a trusted external helper or compare each accepted spelling explicitly.

Arguments are a moving ten-slot window

Inside a script, %0 through %9 refer to the batch filename and the first nine visible arguments. FreeCOM’s SHIFT moves that entire window: after one shift, old %1 becomes %0, old %2 becomes %1, and the previously hidden argument enters %9. SHIFT DOWN reverses a shift without moving before the original start.

@ECHO OFF
:NEXT
IF "%1"=="" GOTO END
ECHO Argument: %1
SHIFT
GOTO NEXT
:END

This loop intentionally leaves %0 behind after the first shift. A script that needs its original filename later should save it before shifting:

SET SCRIPT=%0

Empty-argument detection with IF "%1"=="" is conventional, but an argument containing a quote or command metacharacter can still disturb parsing. DOS batch is appropriate for controlled startup and maintenance parameters, not hostile input.

IF supports three portable condition families

FreeCOM documents IF [NOT] EXIST file command, IF [NOT] ERRORLEVEL number command, and string equality using ==. It does not document Windows comparison operators such as EQU, NEQ, LSS, or GTR.

IF ERRORLEVEL n means greater than or equal to n. Therefore, tests that assign different handling to multiple codes must run from highest to lowest.

PROGRAM.EXE
IF ERRORLEVEL 3 GOTO FATAL
IF ERRORLEVEL 2 GOTO RETRY
IF ERRORLEVEL 1 GOTO WARNING
GOTO SUCCESS

Using IF %ERRORLEVEL% NEQ 0 combines two assumptions that are not portable to FreeCOM: %ERRORLEVEL% as a synthetic environment expansion and NEQ as an operator. Use the documented IF ERRORLEVEL 1 form unless the external program’s manual defines another convention.

Exit codes belong to the program that just ran. An intervening command may change the current error level, so test immediately. Also verify each program’s documentation; DOS has conventions, not a universal guarantee that every nonzero value means the same class of failure.

FOR repeats one command over words or matches

FreeCOM’s FOR walks words and wildcard patterns from left to right. In a batch file, doubled percent signs are the widely portable form:

FOR %%F IN (*.TXT) DO ECHO %%F
FOR %%N IN (ONE TWO THREE) DO ECHO %%N

FreeCOM accepts unusual variations in the number of percent characters if they match consistently, but depending on that relaxation makes scripts less portable to other DOS command interpreters. Keep %%F in scripts and %F at an interactive prompt.

This is the DOS FOR, not cmd.exe’s extended parser. There is no documented FOR /F, recursive /R, numeric /L, tokenization grammar, or parenthesized multi-command body. If each item requires several commands, call a separate batch file:

FOR %%F IN (*.TXT) DO CALL ONEFILE.BAT %%F

FreeCOM warns that redirection in FOR applies to the repeated command. FOR %%F IN (*.TXT) DO ECHO %%F >LIST.TXT repeatedly overwrites the file. To accumulate output, use >>, and test on disposable data before relying on redirection behavior across shells.

GOTO supplies branches, not functions

GOTO label continues at a label in the same batch file. If duplicate labels exist, FreeCOM uses the first, so labels should be unique. Conditional branches combine IF and GOTO.

FreeCOM does not document CALL :LABEL or the virtual :EOF target from Windows command processing. A portable FreeCOM “subroutine” is another batch file invoked with CALL:

REM MAIN.BAT
CALL GREET.BAT Alice
IF ERRORLEVEL 1 GOTO ERROR
ECHO Back in MAIN.BAT
GOTO END
:ERROR
ECHO GREET.BAT failed.
:END

Without CALL, starting another batch file replaces the current batch context and terminates the earlier scripts rather than returning. FreeCOM supports a minimum nested-batch depth defined at build time; unbounded recursive calls can still exhaust memory or nesting limits.

QUIT ends the current script and can set an error level, while CANCEL terminates all running scripts. Their exact availability can depend on how FreeCOM was built, so scripts intended for multiple DOS shells should use documented common constructs and a natural end-of-file where possible.

Redirection and pipes use DOS resources

> replaces a file, >> appends, and < supplies standard input. Confirm destination variables before any redirect because the shell opens the target as part of command execution.

FreeCOM simulates pipelines with temporary files because DOS is not a multitasking system. A chain conceptually runs the first command into a temporary file, feeds that file to the next command, and removes intermediates. The TEMP directory therefore needs free space and write access, and sensitive pipeline data may exist briefly on disk.

Avoid pipelines on a nearly full floppy, a read-only medium, or a directory containing irreplaceable files with colliding names. Set TEMP to a controlled local path and clean only files your script created with names it can identify safely.

Build scripts around explicit failure boundaries

A dependable FreeDOS batch file starts with known environment assumptions, validates required files and directories, prints targets before changes, checks ERRORLEVEL immediately, and preserves source data until output is verified. Backups and test images matter more than clever syntax.

Keep scripts compatible with the interpreter that will run them. FreeCOM adds useful features such as SET /P, SHIFT DOWN, aliases, and optional tracing, but Windows examples found online often depend on cmd.exe extensions. Run COMMAND /?, consult the installed FreeCOM help, and test a minimal case before adopting unfamiliar syntax.

Batch remains effective for boot setup, package orchestration, file copying, and simple decisions precisely because its model is small. Once a task needs robust input escaping, data structures, arithmetic, complex parsing, transactions, or concurrency, a compiled FreeDOS utility or a language package is safer than stretching command substitution beyond its design.

Related:

Sources:

Comments