How to Display Data in a Table with Aligned Columns in Batch Script
Raw output from commands like dir or tasklist is often difficult to read because the columns don't line up vertically. If you are building an administrative tool or a monitoring dashboard in Batch, presenting your data in a clean, aligned table is essential for professionalism and readability.
In this guide, we will demonstrate how to use string padding and the <nul set /p command to create perfectly aligned columns in your Batch script output.
The Challenge: Variable Length Strings
If you try to print columns using spaces, the alignment breaks as soon as one filename or username is longer than the others.
Wrong Way:
echo User: %user% Status: %status%
:: Result (Uneven):
:: User: admin Status: Active
:: User: guestuser Status: Locked
Method 1: The "Fixed-Width Padding" Trick
The most robust way to align columns in Batch is to "pad" your data with a string of spaces and then take a fixed-length substring.
The Padding Concept
If we want a column to be exactly 15 characters wide:
- Add 15 spaces to the end of the text.
- Take the first 15 characters of that result.
Implementation Script
@echo off
setlocal enabledelayedexpansion
:: Define our space padding (must be at least as wide as the widest column)
set "pad= "
echo USERNAME STATUS ROLE
echo ------------------------------------------
:: Process our data (simulated here with a loop)
for %%A in ("admin:Active:Admin" "jdoe:Inactive:User" "guest:Active:User") do (
:: Parse the colon-delimited string
for /F "tokens=1,2,3 delims=:" %%a in ("%%~A") do (
set "col1=%%a!pad!"
set "col2=%%b!pad!"
set "col3=%%c"
:: Print only the first N characters of each padded column
echo !col1:~0,15! !col2:~0,11! !col3!
)
)
endlocal
pause
Method 2: Dynamic Column Widths
If you don't know the maximum width beforehand, you can't hardcode the padding. However, you can use the same logic to ensure everything stays relatively clean by using a large buffer.
@echo off
setlocal enabledelayedexpansion
set "pad= "
echo [Process Name] [PID]
echo ------------------------------
:: Capture process names and PIDs from tasklist
:: skip=3 skips the tasklist header lines
for /F "skip=3 tokens=1,2" %%i in ('tasklist') do (
set "pname=%%i!pad!"
echo !pname:~0,25! %%j
)
endlocal
pause
Method 3: Using the Tab Character
You can use a literal tab character to separate columns. This is simpler than manual padding but less precise, since tab stops are fixed at every 8 columns and cannot be customized in most terminals.
@echo off
setlocal enabledelayedexpansion
:: Capture a literal tab character
for /F "delims=" %%t in ('echo prompt $H ^| cmd') do set "TAB= "
echo Column A!TAB!Column B!TAB!Column C
echo ---------------------------------------
echo Data 1!TAB!Data 2!TAB!Data 3
endlocal
pause
The TAB variable above must contain a literal tab character (ASCII 9). In many text editors, you need to ensure tabs are not converted to spaces. The fixed-width padding approach (Methods 1 and 2) is generally more reliable for precise alignment.
Creating Borders and Headers
To make your table look truly professional, surround it with ASCII borders.
@echo off
setlocal enabledelayedexpansion
set "pad= "
echo +----------------------+------------+
echo ^| NAME ^| STATUS ^|
echo +----------------------+------------+
set "n1=System Check!pad!"
set "n2=Database Sync!pad!"
set "s1=ONLINE"
set "s2=OFFLINE"
:: Build padded status values
:: ANSI color codes add non-printable characters, so we pad the visible text
:: and wrap the color around it separately.
set "s1_text=ONLINE!pad!"
set "s2_text=OFFLINE!pad!"
echo ^| !n1:~0,20! ^| !s1_text:~0,10! ^|
echo ^| !n2:~0,20! ^| !s2_text:~0,10! ^|
echo +----------------------+------------+
endlocal
pause
Summary Checklist
- Delayed Expansion: You MUST use
setlocal enabledelayedexpansionand!variable!to handle strings inside loops accurately. - The Padding Formula: Append spaces to the value, then take a fixed-width substring:
set "col=!value!!pad!"followed by!col:~0,width!. - ANSI Color Caveat: ANSI escape codes contain non-printable characters that occupy zero visible width but do count in substring operations. Pad the visible text first, then wrap colors around the padded result.
- Terminal Width: Ensure your total table width doesn't exceed the terminal width (typically 80 or 120 characters) to avoid line wrapping which breaks the table layout.
Conclusion
Presenting data in tables transforms a "quick and dirty" script into a polished utility. By mastering text padding and fixed-width substrings, you can ensure your report data is always easy to read, regardless of how long the input strings are. This level of visual organization is key to building trusted tools for system administration and user interaction.