43

It look like set tabstop=4 in VIM, but I don't know how to set it in bash

for example:

echo -e "1234567890\t321\n1\t2\n123\t1"

current output:

1234567890      321
1       2
123     1

I want output like this:

1234567890  321
1   2
123 1

It can be shown in anywhere, just like cat somefile or php -r 'echo "\t123";'

How can I set tab width in bash?

wjandrea
  • 28,235
  • 9
  • 60
  • 81
Zheng Kai
  • 3,473
  • 3
  • 17
  • 23
  • It seems as if you can't change it (that's the answers I found). You could do spaces instead, but I guess you know that :p – keyser May 28 '12 at 10:06

6 Answers6

82

That's not a property of your shell (or php or cat). It's your terminal that manages the output.

Use the tabs command to change the behavior:

$ tabs 4

$ echo -e "a\tb"      
a   b
$ tabs 12

$ echo -e "a\tb" 
a           b

(tabs is specified in POSIX, and output above is "faked": it's still a tab character between the two letters.)

Mat
  • 202,337
  • 40
  • 393
  • 406
  • 5
    A note: =tabs= is specified in **Unix** (POSIX with XSI option), not POSIX. Systems that conform to POSIX but not to Unix are not required to implement a =tabs= command. – Stephane Chazelas Sep 11 '12 at 15:11
  • 6
    Addition: Pager "less" is not affected, so use "less -x4"; For "git diff" use "git config --global core.pager 'less -x4'" – Mikl Jul 10 '14 at 17:52
  • it doesn't effect vi editor on macOS terminal ssh Linux – Necktwi Feb 04 '18 at 08:29
  • @neckTwi: vi has its own settings – Mat Feb 04 '18 at 08:35
  • 1
    I know it's super old, but it's surprising to me that other programs like less and vim don't query the terminal about their tab stops before displaying the current file – dlamblin May 06 '23 at 00:59
3

tabs 4 results in the following tabstop positions. Which isn't quite what you asked for.

tab stop positions 4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80
         1         2         3         4         5         6         7         8
12345678901234567890123456789012345678901234567890123456789012345678901234567890
   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *

You asked for this..

tab stop positions 5,9,13,17,21,25,29,33,37,41,45,49,53,57,61,65,69,73,77,80
         1         2         3         4         5         6         7         8
12345678901234567890123456789012345678901234567890123456789012345678901234567890
    *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *  *

Specifying tabs with a single number creates an implicit list that starts from 0.
To create an explicit list such as what you asked for. Provide a comma or space separated list of tab stop positions.
Like so: tabs 5,9,13,17,21,25,29,33,37,41,45,49,53,57,61,65,69,73,77

See man tabs and tabs -v for more details.

NOYB
  • 625
  • 8
  • 14
1

You can set either regular or irregular intervals using the tabs utility. It will work whether you're doing your own output, using cat to output a file that already includes tabs or using the output of a program you don't control.

However, if you're controlling your output it's preferable to use printf instead of echo and format strings instead of tabs.

$ printf '%-12s%8.4f %-8s%6.2f\n' 'Some text' 23.456 'abc def' 11.22
Some text    23.4560 abc def  11.22
$ format='%*s%*.*f %*s%*.*f\n'
$ printf "$format" -12 'Some text' 8 4 23.456 -8 'abc def' 6 2 11.22
Some text    23.4560 abc def  11.22

Unless you want someone else to be able to control the output of your program using the tabs utility.

Dennis Williamson
  • 346,391
  • 90
  • 374
  • 439
1

You can use setterm to set this

setterm -regtabs 4

I put it in my .bash_profile but its not bash related specifically

carpii
  • 1,917
  • 4
  • 20
  • 24
0

This works for me.

~/.bash_profile

# Set the tab stops
if [ -f ~/.bash_tab_stops ]; then
    . ~/.bash_tab_stops
fi

~/.bash_tab_stops

tab_width=4
terminal_width=$( stty size | awk '{print $2}' )

set_tab_stops() {
    local tab_width=$1 terminal_width=$2 tab_stops=''
    for (( i=1+$tab_width; $i<$terminal_width; i+=$tab_width )); do
        tab_stops+=$i','
    done
    tabs $tab_stops
}

set_tab_stops $tab_width $terminal_width

GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)
PuTTY Release 0.73 Build platform: 64-bit x86 Windows
Linux VPS 3.10.0-1127.18.2.el7.centos.plus.x86_64

NOYB
  • 625
  • 8
  • 14
0

If you want an offset for the first tab (e.g. for git diff) you can use shell expansion to get stepped numbers:

tabs {5..300..4}

In the above, 5 is the first tab's width, the second number is your terminal width, the last is your regular tab width.

Walf
  • 8,535
  • 2
  • 44
  • 59