Skip to main content

How to Encode Text into ROT13 or Decode Text from ROT13 in Batch Script

ROT13 (Rotate 13) is a simple substitution cipher that replaces every letter with the 13th letter following it in the alphabet. Because the alphabet has 26 letters, ROT13 is its own inverse, applying it twice returns the original text. While not secure, it is frequently used in online forums to obscure puzzle spoilers or punchlines.

In this guide, we will demonstrate how to build a functional ROT13 encoder/decoder in a Batch script.

The Strategy: Character Mapping via Substitution​

Batch supports basic string replacement through %variable:Search=Replace%, but ROT13 can’t be done safely with sequential replacements on the same string (you’d “re-rotate” characters you already changed).

Instead, we’ll:

  1. define a source alphabet map and a rotated alphabet map,
  2. iterate through the input string one character at a time,
  3. find the character’s index in the source map,
  4. append the character at the same index from the rotated map.

Implementation Script (Pure Batch)​

@echo off
setlocal EnableDelayedExpansion

:: 1. Ask user for input
set /p "userInput=Enter text to ROT13 encode/decode: "

if not defined userInput (
echo [ERROR] No input provided.
pause
exit /b 1
)

:: 2. Define aligned character maps (26 lowercase + 26 uppercase = 52 chars)
set "chars=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
set "rot13=nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM"

:: 3. Calculate input length
set /a len=0
:string_length
if not "!userInput:~%len%,1!"=="" (
set /a len+=1
goto string_length
)

:: If len=0, nothing to do (already guarded above, but kept safe)
if %len% leq 0 (
echo [ERROR] No input provided.
pause
exit /b 1
)

:: 4. Process character-by-character
set "output="
set /a last=len-1

for /l %%A in (0,1,!last!) do (
set "currentChar=!userInput:~%%A,1!"
set "matched="

:: Search currentChar inside chars map
for /l %%B in (0,1,51) do (
if "!currentChar!"=="!chars:~%%B,1!" (
set "output=!output!!rot13:~%%B,1!"
set "matched=1"
)
)

:: If not a mapped letter, keep the original character
if not defined matched (
set "output=!output!!currentChar!"
)
)

echo.
echo ==========================================
echo ORIGINAL: !userInput!
echo ROT13 : !output!
echo ==========================================
pause
endlocal
warning

This implementation uses Delayed Expansion (EnableDelayedExpansion). If the input contains exclamation marks (!), Windows CMD may remove or alter them during processing. For arbitrary text (including !), use the PowerShell method below.

tip

This approach is intentionally “manual” (nested loops) to stay 100% Batch-native. It’s fine for short strings, but it will be slow for large paragraphs.

How It Works​

  1. Map alignment: chars contains a-z then A-Z. rot13 is the same set rotated by 13 positions (a→n, n→a, etc.).
  2. Length calculation: Batch has no built-in .length(), so the :string_length loop checks the next character until it returns empty.
  3. Index matching: For each input character, we scan all 52 positions in chars. If we find a match at index i, we append rot13[i].
  4. Non-letters preserved: Spaces, punctuation, and digits aren’t in chars, so they fall through and are appended unchanged.

Alternative: Using a PowerShell Bridge (Much Faster)​

For long strings, delegate ROT13 to PowerShell (fast and clean). This version prompts in Batch and passes the string as a PowerShell argument.

@echo off
setlocal

:: Prompt user
set /p "str=Enter text to ROT13 encode/decode: "
if not defined str (
echo [ERROR] No input provided.
pause
exit /b 1
)

:: Call PowerShell to perform ROT13
for /f "usebackq delims=" %%I in (`powershell -NoProfile -Command ^
"$s = '%str%';" ^
"$a = $s.ToCharArray();" ^
"for ($i=0; $i -lt $a.Length; $i++) {" ^
" $c = [int][char]$a[$i];" ^
" if (($c -ge 65 -and $c -le 77) -or ($c -ge 97 -and $c -le 109)) { $a[$i] = [char]($c+13) }" ^
" elseif (($c -ge 78 -and $c -le 90) -or ($c -ge 110 -and $c -le 122)) { $a[$i] = [char]($c-13) }" ^
"}" ^
"-join $a"`) do set "encoded=%%I"

echo ROT13: %encoded%
pause
endlocal
warning

Passing arbitrary user input from Batch to PowerShell is tricky when the text contains special characters (notably quotes). If you need to support completely arbitrary text, the most reliable approach is to write the input to a temporary file and have PowerShell read the file.

Why Implement ROT13 in Batch?​

  1. Educational exercises: It’s a compact way to learn substrings, loops, and mapping logic in Batch.
  2. Basic obfuscation: Useful for hiding spoilers or casual hints in logs/config files (not real security).
  3. Portability: Provides a no-dependencies option when PowerShell is restricted and you want a pure .bat solution.

Conclusion​

A ROT13 encoder/decoder is a practical demonstration of Batch string slicing and mapping. While ROT13 is not cryptographically secure, implementing it in Batch is a useful exercise and can provide lightweight text obfuscation in simple workflows.