Skip to main content

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:

  1. Add 15 spaces to the end of the text.
  2. 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
Note on tab characters

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

  1. Delayed Expansion: You MUST use setlocal enabledelayedexpansion and !variable! to handle strings inside loops accurately.
  2. The Padding Formula: Append spaces to the value, then take a fixed-width substring: set "col=!value!!pad!" followed by !col:~0,width!.
  3. 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.
  4. 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.