Fix Terminal Tab Stops with the tabs Command

The tabs command writes control sequences straight to your terminal, clearing or setting tab stops without touching a single file. Use it whenever a report, source listing or full-screen program expects tab stops somewhere other than where your terminal currently has them. This guide covers the ncurses implementation supplied by Ubuntu's ncurses-bin package, version 6.4+20240113-1ubuntu2.2, and takes about five minutes to try.

The command changes terminal state, not a file, so test it in a spare terminal or a disposable shell session.

Before you start

A tab stop is a position held by the terminal emulator itself, not by your shell. tabs does not edit your shell configuration and normally does not need sudo. The settings belong to the current terminal session and can persist until another program changes them or the terminal is reset.

The command relies on the terminfo entry selected by TERM. That entry must provide both clear_all_tabs and set_tab, or the command cannot do its job. Check the terminal type before troubleshooting a layout:

printf 'TERM=%s\n' "$TERM"
infocmp "$TERM" > /dev/null && echo 'terminfo entry found'

Expected output includes your terminal type and terminfo entry found. A missing or incorrect TERM can make a correct tab layout look broken. Do not copy a guessed value from another machine: fix the terminal or multiplexer configuration that set it instead.

1. Make the terminal use hard tabs

The ncurses manual recommends hard-tab mode for the terminal line discipline. Apply it in the shell attached to the terminal you want to configure:

stty tab0

This is an ordinary user command, but it changes the terminal's input and output handling for that device, so do not run it blindly inside a script sharing a terminal with another interactive task. If other settings on the shell have also become confused, stty sane is a broader repair, though it resets more than tab handling. For tab stops alone, continue with tabs -8.

2. Reset to the standard interval

Start from a known layout before applying a special one:

tabs -8

This clears the existing stops and sets a repeated stop every eight columns, starting at column 1. It is also the recommended preparation before launching curses applications, because normal terminal initialisation does not guarantee old hardware tab stops have been removed.

There is no success message: the command just sends control sequences. Verify the requested layout without changing it by adding -d and -n:

tabs -n -d -8

The output is a ruler followed by two rows: the first shows expected positions, the second shows the terminal's current positions. A typical terminal shows asterisks at every eighth column in both rows. -n is a no-op, so this checks and debugs without modifying the terminal.

3. Choose a repeated interval

A negative number is an implicit list, and the number is the spacing, not the first column:

tabs -5
tabs -n -d -5

The first command sets stops at columns 1, 6, 11, 16 and onward to the right margin. The second prints the comparison for inspection. Use -0 to clear all stops:

tabs -0

Clearing stops is reversible. Run tabs -8 to restore the usual interval, then tabs -n -d -8 to check it. If the display still looks wrong, the program printing the data may be expanding tabs itself, or its assumptions may disagree with the terminal database.

4. Set an explicit layout

For a report with irregular columns, pass one increasing list after the options. Values are positive column numbers, separated by commas or spaces:

tabs 1,6,11,16,21
tabs -n -d 1,6,11,16,21

The first command applies the five stops; the second checks the same list without applying it. The list must increase left to right. A relative form helps when the spacing repeats:

tabs 1,+5,+5,+5,+5

Each + value here adds to the preceding stop, producing the same positions as the comma-separated example. Keep the list as one shell argument when using commas; with spaces the shell passes several arguments, so quote the list if it is generated or assembled in a script.

Do not assume every terminal accepts an unlimited number of stops. The ncurses program tries to set stops up to the right margin, but the terminal may impose its own limit. Use -d -n to see what the command expects against what the terminal reports.

5. Use a predefined layout when it fits

Several named options match conventional programming and data formats. The normal COBOL layout is -c, FORTRAN is -f:

tabs -c
tabs -n -d -f

The first applies the COBOL stops; the second only displays the FORTRAN expectation and comparison. Other predefined forms include -a and -a2 for IBM S/370 assembler, -c2 and -c3 for compact COBOL, -p for PL/I, -s for SNOBOL and -u for UNIVAC 1100 assembler. Prefer an explicit list when the layout is a local convention readers cannot infer from the option name.

6. Set margins, choose a terminal type, and capture sequences

Some terminals support a left margin. +m sets it, defaulting to 10 columns when no value follows; +m0 returns the margin to the left edge. If the terminal lacks the required terminfo capability, ncurses imitates the effect by adjusting the stops it sends, leaving the hardware left margin unchanged. Setting or resetting a left margin can also reset the right margin, so check the result before relying on it:

tabs +m0
tabs +m12
tabs -n -d +m12

Use -T only when you deliberately need a different terminfo entry, such as testing a remote terminal description:

tabs -T xterm-256color -n -d -8

Normally leave -T out so tabs uses TERM. Supplying the wrong type can send sequences your terminal does not understand. If TERM is unset, the ncurses implementation falls back to ansi+tabs, which is not a reason to override a correctly configured terminal.

To prepare sequences without changing the terminal immediately, redirect standard output to a file:

tabs -8 > /tmp/tabs-eight.bin
cat /tmp/tabs-eight.bin

Redirecting stops the first command from changing the terminal. cat applies the saved sequences when it writes them to the screen. The file holds terminal control bytes, so do not open it in a text editor or paste it into an untrusted terminal. Remove it after use with rm -- /tmp/tabs-eight.bin; it is safe to recreate.

Common traps

Done means