skills/batch-files/SKILL.md
Expert-level Windows batch file (.bat/.cmd) skill for writing, debugging, and maintaining CMD scripts. Use when asked to "create a batch file", "write a .bat script", "automate a Windows task", "CMD scripting", "batch automation", "scheduled task script", "Windows shell script", or when working with .bat/.cmd files in the workspace. Covers cmd.exe syntax, environment variables, control flow, string processing, error handling, and integration with system tools.
npx skillsauth add williamlimasilva/.copilot batch-filesInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
A comprehensive skill for creating, editing, debugging, and maintaining Windows batch files (.bat/.cmd) using cmd.exe. Applies to CLI tool development, system administration automation, scheduled tasks, file operations scripting, and PATH-based executable scripts.
.bat or .cmd filesbin/ folder on PATHbin/ directory on PATH for distributing scripts as commands.BAT;.CMD (default on Windows)cmd.exe processes each line through four stages in order:
%VAR% tokens are replaced with environment variable values. %0–%9 reference batch arguments. %* expands to all arguments.^ escapes special characters (& | < > ^). Quotation marks prevent interpretation of enclosed special characters. In batch files, %% yields a literal %.|), compound commands (&, &&, ||), and parenthesized groups ( ).> overwrites, >> appends, < reads input, 2> redirects stderr, 2>&1 merges stderr into stdout, >NUL discards output.set _MY_VAR=Hello World
echo %_MY_VAR%
set _MY_VAR=
set with no arguments lists all variablesset _PREFIX lists variables starting with _PREFIX= — set name = val sets variable "name " to " val"| Variable | Value |
|----------|-------|
| %CD% | Current directory |
| %DATE% | System date (locale-dependent) |
| %TIME% | System time HH:MM:SS.mm |
| %RANDOM% | Pseudorandom number 0–32767 |
| %ERRORLEVEL% | Exit code of last command |
| %USERNAME% | Current user name |
| %USERPROFILE% | Current user profile path |
| %TEMP% / %TMP% | Temporary file directory |
| %PATHEXT% | Executable extensions list |
| %COMSPEC% | Path to cmd.exe |
setlocal
set _LOCAL_VAR=scoped value
endlocal
REM _LOCAL_VAR is no longer defined here
To return a value from a scoped block:
endlocal & set _RESULT=%_LOCAL_VAR%
Variables inside parenthesized blocks are expanded at parse time. Use delayed expansion for runtime evaluation:
setlocal EnableDelayedExpansion
set _COUNT=0
for /l %%i in (1,1,5) do (
set /a _COUNT+=1
echo !_COUNT!
)
endlocal
!VAR! expands at execution time (delayed)%VAR% expands at parse time (immediate)if exist "output.txt" echo File found
if not defined _MY_VAR echo Variable not set
if "%_STATUS%"=="ready" (echo Go) else (echo Wait)
if %ERRORLEVEL% neq 0 echo Command failed
Comparison operators: equ, neq, lss, leq, gtr, geq. Use /i for case-insensitive string comparison.
command1 & command2 & REM Always run both
command1 && command2 & REM Run command2 only if command1 succeeds
command1 || command2 & REM Run command2 only if command1 fails
REM Iterate over a set of values
for %%i in (alpha beta gamma) do echo %%i
REM Numeric range: start, step, end
for /l %%i in (1,1,10) do echo %%i
REM Files in a directory
for %%f in (*.txt) do echo %%f
REM Recursive file search
for /r %%f in (*.log) do echo %%f
REM Directories only
for /d %%d in (*) do echo %%d
REM Parse command output
for /f "tokens=1,2 delims=:" %%a in ('ipconfig ^| findstr "IPv4"') do echo %%b
REM Parse file lines
for /f "usebackq tokens=*" %%a in ("data.txt") do echo %%a
goto :main_logic
:usage
echo Usage: %~nx0 [options]
exit /b 1
:main_logic
echo Running main logic...
goto :eof
goto :eof exits the current batch or subroutine. Labels start with :.
| Syntax | Value |
|--------|-------|
| %0 | Script name as invoked |
| %1–%9 | Positional arguments |
| %* | All arguments (unaffected by SHIFT) |
| %~1 | Argument 1 with enclosing quotes removed |
| %~f1 | Full path of argument 1 |
| %~d1 | Drive letter of argument 1 |
| %~p1 | Path (without drive) of argument 1 |
| %~n1 | File name (no extension) of argument 1 |
| %~x1 | Extension of argument 1 |
| %~dp0 | Drive and path of the batch file itself |
| %~nx0 | File name with extension of the batch file |
| %~z1 | File size of argument 1 |
| %~$PATH:1 | Search PATH for argument 1 |
:parse_args
if "%~1"=="" goto :args_done
if /i "%~1"=="--help" goto :usage
if /i "%~1"=="--output" (
set "_OUTPUT_DIR=%~2"
shift
)
shift
goto :parse_args
:args_done
set _STR=Hello World
echo %_STR:~0,5% & REM "Hello"
echo %_STR:~6% & REM "World"
echo %_STR:~-5% & REM "World"
echo %_STR:~0,-6% & REM "Hello"
set _STR=Hello World
echo %_STR:World=Earth% & REM "Hello Earth"
echo %_STR:Hello=% & REM " World" (remove "Hello")
if not "%_STR:World=%"=="%_STR%" echo Contains "World"
Functions use labels, CALL, and SETLOCAL/ENDLOCAL:
@echo off
call :greet "Jane Doe"
echo Result: %_GREETING%
exit /b 0
:greet
setlocal
set "_MSG=Hello, %~1"
endlocal & set "_GREETING=%_MSG%"
exit /b 0
call :label args invokes a functionexit /b returns from the function (not the script)endlocal & set trick to pass values out of a scoped blockset /a performs 32-bit signed integer arithmetic:
set /a _RESULT=10 * 5 + 3
set /a _COUNTER+=1
set /a _REMAINDER=14 %% 3 & REM Use %% for modulo in batch files
set /a _BITS="255 & 0x0F" & REM Bitwise AND
Supported operators: + - * / %% ( ) and bitwise & | ^ ~ << >>.
Hexadecimal (0xFF) and octal (077) literals are supported.
0 = success1)mycommand.exe
if %ERRORLEVEL% neq 0 (
echo ERROR: mycommand failed with code %ERRORLEVEL%
exit /b %ERRORLEVEL%
)
command1 || (echo command1 failed & exit /b 1)
command2 || (echo command2 failed & exit /b 1)
exit /b 0 & REM Return success from a batch/function
exit /b 1 & REM Return failure
cmd /c "exit /b 42" & REM Set ERRORLEVEL to 42 inline
| Command | Purpose |
|---------|---------|
| DIR | List directory contents |
| COPY | Copy files |
| XCOPY | Extended copy with subdirectories (legacy) |
| ROBOCOPY | Robust copy with retry, mirror, logging |
| MOVE | Move or rename files |
| DEL | Delete files |
| REN | Rename files |
| MD / MKDIR | Create directories |
| RD / RMDIR | Remove directories |
| MKLINK | Create symbolic or hard links |
| ATTRIB | View or set file attributes |
| TYPE | Print file contents |
| MORE | Paginated file display |
| TREE | Display directory structure |
| REPLACE | Replace files in destination with source |
| COMPACT | Show or set NTFS compression |
| EXPAND | Extract from .cab files |
| MAKECAB | Create .cab archives |
| TAR | Create or extract tar archives |
| Command | Purpose |
|---------|---------|
| FIND | Search for literal strings |
| FINDSTR | Search with limited regular expressions |
| SORT | Sort lines alphabetically |
| CLIP | Copy piped input to clipboard |
| FC | Compare two files |
| COMP | Binary file comparison |
| CERTUTIL | Encode/decode Base64, compute hashes |
| Command | Purpose |
|---------|---------|
| SYSTEMINFO | Full system configuration |
| HOSTNAME | Display computer name |
| VER | Windows version |
| WHOAMI | Current user and group info |
| TASKLIST | List running processes |
| TASKKILL | Terminate processes |
| WMIC | WMI queries (drives, OS, memory) |
| SC | Service control (query, start, stop) |
| DRIVERQUERY | List installed drivers |
| REG | Registry operations (query, add, delete) |
| SETX | Set persistent environment variables |
| Command | Purpose |
|---------|---------|
| PING | Test network connectivity |
| IPCONFIG | IP configuration |
| NSLOOKUP | DNS lookup |
| NETSTAT | Network connections and ports |
| TRACERT | Trace route to host |
| NET USE | Map/disconnect network drives |
| NET USER | Manage user accounts |
| NETSH | Network configuration utility |
| ARP | ARP cache management |
| ROUTE | Routing table management |
| CURL | HTTP requests (Windows 10+) |
| SSH | Secure shell (Windows 10+) |
| Command | Purpose |
|---------|---------|
| SCHTASKS | Create and manage scheduled tasks |
| TIMEOUT | Wait N seconds (Vista+) |
| START | Launch programs asynchronously |
| RUNAS | Run as different user |
| SHUTDOWN | Shutdown or restart |
| FORFILES | Find files by date and execute commands |
| Command | Purpose |
|---------|---------|
| WHERE | Locate executables in PATH |
| DOSKEY | Create command macros |
| CHOICE | Prompt for single-key input |
| MODE | Configure console size and ports |
| SUBST | Map folder to drive letter |
| CHCP | Get or set console code page |
| COLOR | Set console colors |
| TITLE | Set console window title |
| ASSOC / FTYPE | File type associations |
Parentheses turn compound commands into a single unit for redirection or conditional execution:
(echo Line 1 & echo Line 2) > output.txt
if exist "data.csv" (
echo Processing...
call :process "data.csv"
) else (
echo No data found.
)
The caret ^ escapes the next character:
echo Total ^& Summary & REM Outputs: Total & Summary
echo 100%% complete & REM Outputs: 100% complete (in batch)
echo Line one^
Line two & REM Caret escapes the newline
After a pipe, triple caret is needed: echo x ^^^& y | findstr x
* matches any sequence of characters? matches a single character (or zero at end of period-free segment)dir *.txt & REM All .txt files
ren *.jpeg *.jpg & REM Bulk rename
command > file.txt & REM Overwrite stdout to file
command >> file.txt & REM Append stdout to file
command 2> errors.log & REM Redirect stderr
command > all.log 2>&1 & REM Merge stderr into stdout
command < input.txt & REM Read stdin from file
command > NUL 2>&1 & REM Discard all output
@echo off
setlocal EnableDelayedExpansion
REM ============================================================
REM Script: example.bat
REM Purpose: Describe what this script does
REM ============================================================
call :main %*
exit /b %ERRORLEVEL%
:main
call :parse_args %*
if not defined _TARGET (
echo ERROR: --target is required. 1>&2
call :usage
exit /b 1
)
echo Processing: %_TARGET%
exit /b 0
:parse_args
if "%~1"=="" exit /b 0
if /i "%~1"=="--target" set "_TARGET=%~2" & shift
if /i "%~1"=="--help" call :usage & exit /b 0
shift
goto :parse_args
:usage
echo Usage: %~nx0 --target ^<path^> [--help]
echo.
echo Options:
echo --target Path to process (required)
echo --help Show this help message
exit /b 0
@echo off and setlocal — Prevents noisy output and variable leakage to the caller.if not defined and if not exist."%~1" and "%_MY_PATH%" to handle spaces and special characters safely.exit /b instead of exit — Avoids closing the parent console window.exit /b 0 for success, non-zero for specific failures.%~dp0 for script-relative paths — Ensures the script works regardless of the caller's working directory.ROBOCOPY over XCOPY — More reliable, supports retry, mirroring, and logging.EnableDelayedExpansion when modifying variables inside loops or parenthesized blocks.echo ERROR: message 1>&2 keeps stdout clean for piping.REM for comments — :: can cause issues inside FOR loop bodies.&, |, or > can inject commands. Always quote: "%_USER_INPUT%".SETLOCAL — Prevents variable values from leaking to parent processes.DEL, RD, or ROBOCOPY to prevent unintended deletion.SET /P for sensitive input — Input is visible and stored in console history. Use a dedicated credential tool when possible.| Technique | How |
|-----------|-----|
| Trace execution | Remove @echo off or use @echo on temporarily |
| Step through | Add PAUSE between sections |
| Check error level | echo Exit code: %ERRORLEVEL% after each command |
| Inspect variables | set _MY_ to list all variables starting with _MY_ |
| Delayed expansion issues | Variable inside ( ) block not updating? Enable !VAR! syntax |
| FOR loop %% vs % | Use %%i in batch files, %i on the command line |
| Spaces in SET | set name=value not set name = value |
| Caret in pipes | After a pipe, use ^^^ to escape special chars |
| Parentheses in SET /A | Escape with ^( and ^) inside if blocks, or use quotes |
| Double percent for modulo | set /a r=14 %% 3 in batch files |
When batch scripting reaches its limits, these tools extend cmd.exe capabilities:
| Tool | Purpose | |------|---------| | Cygwin | Full POSIX environment on Windows (grep, sed, awk, ssh) | | MSYS2 | Lightweight Unix tools and package manager (pacman) | | WSL | Windows Subsystem for Linux — run native Linux binaries | | GnuWin32 | Individual GNU utilities as native Windows executables | | PowerShell | Modern Windows scripting with .NET integration |
Use batch when you need: fast startup, simple file operations, PATH-based CLI tools, or Task Scheduler integration. Consider PowerShell or WSL for complex data processing, REST APIs, or object-oriented scripting.
| Shortcut | Action |
|----------|--------|
| Tab | Auto-complete file/folder names |
| Up / Down | Navigate command history |
| F7 | Show command history popup |
| F3 | Repeat last command |
| Esc | Clear current line |
| Ctrl+C | Cancel running command |
| Alt+F7 | Clear command history |
The references/ folder contains detailed documentation:
| File | Contents |
|------|----------|
| tools-and-resources.md | Windows tools, utilities, package managers, terminals |
| batch-files-and-functions.md | Example scripts, techniques, best practices links |
| windows-commands.md | Comprehensive A-Z Windows command reference |
| cygwin.md | Cygwin user guide and FAQ |
| msys2.md | MSYS2 installation, packages, and environments |
| windows-subsystem-on-linux.md | WSL setup, commands, and documentation |
The assets/ folder contains starter batch file template data, but as text files:
| Template | Purpose |
|----------|---------|
| executable.txt | Standalone CLI tool with argument parsing |
| library.txt | Reusable function library with CALL-able labels |
| task.txt | Scheduled task / automation script |
tools
Create a new workshop or use an existing directory as one. Handles two paths: (A) use an existing local directory the operator points at, or (B) create a new private GitHub repo in the signed-in account. Never creates a repo inside another repo.
development
Guide for setting up vcpkg in C++ projects, managing dependency versions, and cross-compiling. Covers manifest initialization, CMake and Visual Studio integration, classic-to-manifest migration, version pinning, baselines, overrides, triplets, and cross-compilation. Use when a user is working with vcpkg project setup, installation, version management, or cross-platform builds. For specialized tasks, additional references cover custom registries and overlay ports (references/registries.md), CI/CD and binary caching (references/ci.md), and troubleshooting and dependency lifecycle (references/troubleshooting.md).
testing
Emit structured agent signals — hands-up, blocked, done, checkpoint, partnership. Signals are written as JSON to .signals/ for dashboard consumption and noted in the journal for persistence.
development
Install and configure Markstream streaming Markdown renderers for Vue, React, Svelte, Angular, Nuxt, and Vue 2 applications. Use for package selection, minimal peer dependencies, CSS order, SSR boundaries, streaming mode, and renderer setup.