Est. 1993 Beginner

NT Shell

The Windows NT command shell, CMD.EXE — the 32-bit interactive shell and script interpreter that arrived with Windows NT 3.1 in 1993 and whose NT 4.0 command extensions made 'NT shell scripting' a discipline of its own.

Created by Microsoft (the initial Windows NT command shell is credited to Therese Stowell)

Paradigm Scripting, Procedural
Typing Untyped (every variable is an environment string; SET /A performs integer arithmetic)
First Appeared 1993
Latest Version No independent version; CMD.EXE ships as part of Windows and is still included in Windows 11

NT Shell is the name the 1990s gave to the Windows NT command shell, CMD.EXE, and to the scripting language it runs. CMD.EXE arrived with Windows NT 3.1 in July 1993. It replaced MS-DOS’s COMMAND.COM as both the interactive prompt and the batch-file interpreter for Microsoft’s new 32-bit operating system. Its language started as a compatible superset of DOS batch. With Windows NT 4.0 in 1996 it gained enough new features (integer arithmetic, subroutines, directory-walking and file-parsing FOR loops) that system administrators began to treat “NT shell scripting” as a discipline of its own. Tim Hill’s 1998 reference, Windows NT Shell Scripting, is named for it.

The program still exists. Every current copy of Windows includes CMD.EXE, and Microsoft still documents it. What is historical is the NT Shell identity: a server-room shell tied to the NT product line, before Windows XP brought the NT kernel to everyone and before PowerShell became Microsoft’s main command shell. This page covers the shell as an environment: interactive mode, the NT 4.0 extensions and the admin practices that grew up around it. The scripting dialect as it survives today has its own page, Windows NT Batch, and its DOS ancestor is covered under DOS Batch.

History & Origins

Windows NT was meant to be a portable, protected-mode, multi-user-capable operating system, and COMMAND.COM did not fit. It was a 16-bit real-mode program. The nearest precedent was the CMD.EXE that Microsoft and IBM had written for OS/2 1.0 (December 1987). Hill’s book traces NT’s two script extensions to these two ancestors: .BAT “was inherited from MS-DOS, while the .CMD type came from OS/2.”

For NT, Microsoft wrote a new CMD.EXE as a native console program. Wikipedia credits the initial NT version to Therese Stowell, citing G. Pascal Zachary’s 1994 account of the NT project, Showstopper!. It shipped with Windows NT 3.1 on July 27, 1993. The design had one hard constraint: existing DOS batch files had to keep working. That constraint has shaped every later change.

The bigger change came with Windows NT 4.0 (1996). Hill’s introduction explains why a book was needed at all: “Aren’t scripts just MS-DOS batch files with a fancy name? … Well, batch files have changed. With the release of Windows NT 4.0, the command shell has been given enough new features to fill a book.” Microsoft called these features command extensions. They were on by default and controlled by two CMD switches of the time, /X (enable) and /Y (disable), plus a per-user EnableExtensions registry value. On current Windows the switches are /E:ON and /E:OFF.

Design Philosophy

The NT Shell has no formal specification. Its principles show up in how it behaves:

  1. Backward compatibility is non-negotiable. Hill notes that the extensions “are backward compatible, but they can occasionally cause older Windows NT and MS-DOS scripts to fail.” The fix was not to remove features but to provide a switch that, “in effect, runs an MS-DOS compatible command shell.”
  2. Interactive and script modes are one language. Hill describes the shell as running in either Interactive mode or Script mode. With one or two exceptions, anything that can be typed at the prompt can go in a script, and the reverse.
  3. Everything is an environment variable. There are no types and no data structures. Values are strings in the process environment, and SET /A evaluates integer expressions on top of them. Arrays are simulated with numbered variable names.
  4. The shell is glue. Like a Unix shell, CMD.EXE does little work itself. It sequences external commands such as NET, XCOPY, AT and the Resource Kit utilities, and passes their exit codes along.

Key Features

The interactive shell

NT’s CMD.EXE was a noticeably better interactive environment than COMMAND.COM:

  • Built-in command history and editing. In MS-DOS, DOSKEY was a terminate-and-stay-resident (TSR) program that had to be loaded first. In Windows NT, Hill writes, “these features are built into the shell and are always available; DOSKEY merely provides an interface to control them.” F7 pops up a numbered history list, F9 recalls a command by number, and DOSKEY macros define command aliases.
  • File-name completion that had to be switched on. NT 4.0 could complete file and directory names, but the CompletionChar registry value defaulted to 0x0 (disabled). Hill suggests setting it to 0x9, the Tab key. Microsoft’s current documentation still describes the CompletionChar/PathCompletionChar values and the /F:ON switch, under which Ctrl+D completes directory names and Ctrl+F completes both file and directory names.
  • AutoRun. Unless CMD is started with /D, it runs any command stored in the AutoRun value under HKLM or HKCU\Software\Microsoft\Command Processor before doing anything else. It is the closest thing CMD has to a .profile.
  • Conditional chaining. && runs the next command only if the previous one succeeded, || only if it failed, & sequences commands unconditionally, and parentheses group them.

The NT 4.0 script language

A short script using only features that NT’s extensions added to DOS batch:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
@echo off
if not "%OS%"=="Windows_NT" goto DOSEXIT
setlocal

set /a COUNT=0
for %%F in (*.log) do call :TALLY "%%F"
echo %COUNT% log files found
endlocal
goto :EOF

:TALLY
set /a COUNT+=1
echo   found %1
goto :EOF

:DOSEXIT
echo This script requires Windows NT
  • The %OS% guard. Windows NT always sets OS to Windows_NT. Hill’s skeleton scripts test it on the first lines so that the script exits cleanly on MS-DOS, Windows 3.1, Windows 95 or OS/2. Those lines, and the DOSEXIT section, must therefore use only DOS-compatible syntax.
  • SET /A evaluates integer expressions with C-style operators, including compound assignment such as +=.
  • CALL :label and GOTO :EOF give the language real subroutines with arguments. Before this, batch code reused logic by calling separate .BAT files.
  • Extended FOR and IF. New FOR forms walk directory trees and parse file contents or command output, and IF gains numeric comparison operators such as EQU, NEQ, LSS and LEQ.
  • SETLOCAL / ENDLOCAL keep a script’s variable changes local to the script. OS/2’s CMD reportedly already had both commands.

Windows 2000 later added delayed expansion (!VAR!). It fixes the most notorious trap in the language: a %VAR% inside a parenthesised block is expanded once, when the whole block is parsed, not each time the line runs.

Evolution

ReleaseWhat changed in the NT Shell
Windows NT 3.1 (1993)New 32-bit CMD.EXE; DOS batch compatibility; .BAT and .CMD scripts
Windows NT 4.0 (1996)Command extensions: SET /A, CALL :label, GOTO :EOF, extended FOR/IF; /X and /Y switches
Windows 2000 (2000)Delayed expansion with !VAR!
Windows XP onwardThe NT shell becomes the command prompt on consumer Windows as well
PowerShell era (2006 onward)CMD.EXE kept for compatibility; Microsoft documentation directs advanced users to PowerShell

After Windows 2000 the language changed little. The most important later events happened around it rather than inside it. In 2001 Windows XP moved home users onto NT, so the “NT Shell” became simply the Windows command prompt. Then Microsoft’s object-pipeline shell project, codenamed Monad, shipped as PowerShell in 2006.

Current Relevance

The NT-era name is gone, and so are most of its practices: NT 4.0 domains, the AT-driven Schedule service and the NT Resource Kit. That is why the encyclopedia lists the shell as historical. The interpreter itself is still in use. CMD.EXE ships with Windows 11 and runs the same .BAT and .CMD files, and Microsoft’s Nano Server container images include it, so the Docker command above works on a Windows container host (not on Linux). Microsoft’s current CMD reference describes nearly the same switches and registry values that Hill documented in 1998, with one addition: a note pointing readers to PowerShell.

Why It Matters

The NT Shell carried DOS batch into the 32-bit era without breaking it. Because NT 4.0’s extensions were on by default but could be switched off, a 1985 batch file and a 1997 logon script could run side by side on the same server. NT 4.0 also gave Windows administrators a built-in automation language present “on every installation”, in Hill’s words, years before Windows Script Host or PowerShell. The way that language was extended (opt-in switches, compatibility kept at every step, quirks never removed) explains both why CMD scripting is so awkward and why scripts written for the NT Shell in the 1990s still run.

Timeline

1987
OS/2 1.0, developed jointly by Microsoft and IBM, ships in December 1987 with a command interpreter named CMD.EXE. The .CMD script extension that the NT shell later accepts alongside .BAT comes from OS/2.
1993
Windows NT 3.1 is released on July 27, 1993. Its command shell is a new 32-bit CMD.EXE that runs both interactive commands and .BAT/.CMD scripts, while staying compatible with existing MS-DOS batch files.
1996
Windows NT 4.0 adds a large set of 'command extensions' to CMD.EXE: arithmetic with SET /A, CALL :label subroutines, GOTO :EOF, and new forms of FOR and IF. They are on by default; the /X and /Y switches and the EnableExtensions registry value turn them on or off.
1998
Macmillan Technical Publishing publishes Tim Hill's 'Windows NT Shell Scripting' (ISBN 1-57870-047-7). It is a full reference to the NT 4.0 shell language and says the new features are enough 'to fill a book'.
2000
Windows 2000 adds delayed environment-variable expansion: the !VAR! syntax, turned on with SETLOCAL ENABLEDELAYEDEXPANSION or CMD /V:ON. It was arguably the last major change to how the shell language parses.
2005
An 'NT Shell' entry by an anonymous author appears in the 99 Bottles of Beer collection, dated April 20, 2005 on the site. It is a CMD.EXE script that uses SET /A, the LEQ and NEQ comparison operators, and GOTO :EOF, all of which are command extensions.
2006
Microsoft releases Windows PowerShell 1.0 in November 2006 as its new command-line shell and scripting language. From then on CMD.EXE is maintained for compatibility rather than developed further.
2025
Microsoft still maintains its CMD reference on Microsoft Learn (revised in 2025). The page lists the /E, /F and /V switches and the AutoRun, EnableExtensions and CompletionChar registry values, and it points users who want more advanced capabilities to PowerShell.

Notable Uses & Legacy

Windows NT domain logon scripts

NT domain administrators gave each user account a logon script (set with NET USER /SCRIPTPATH). These .BAT/.CMD files ran on the client at logon to map network drives and set up the environment. Tim Hill's 1998 book ships a complete sample logon script.

Scheduled administration jobs

Scripts run unattended by the Windows NT Schedule service (driven from the AT command) handled backups and housekeeping. NT shell scripters learned to map drives explicitly inside the script, because, as Hill puts it, the Schedule service 'operates independently of a user logon', so the drive mappings a logon script creates are not necessarily available.

Windows NT Resource Kit automation

The command-line utilities in the Windows NT Resource Kit were usually combined in shell scripts for user, registry and server administration. Hill's reference covers both and tags each Resource Kit tool so readers know which scripts will run on a plain NT installation.

Build-tool launchers

Many cross-platform tools still start on Windows through a CMD.EXE script. Examples are the Gradle wrapper's gradlew.bat and Apache Maven's mvn.cmd, which find a Java runtime and start the build from the Command Prompt.

Language Influence

Influenced By

MS-DOS COMMAND.COM OS/2 CMD.EXE

Running Today

Run examples using the official Docker image:

docker pull mcr.microsoft.com/windows/nanoserver:ltsc2022

Example usage:

docker run --rm mcr.microsoft.com/windows/nanoserver:ltsc2022 cmd /c "echo Hello, World!"
Last updated: