443

How do I echo one or more tab characters using a bash script? When I run this code

res='       'x # res = "\t\tx"
echo '['$res']' # expect [\t\tx]

I get this

res=[ x] # that is [<space>x]
Dereckson
  • 1,340
  • 17
  • 30
kalyanji
  • 4,608
  • 2
  • 17
  • 6

10 Answers10

734
echo -e ' \t '

will echo 'space tab space newline' (-e means 'enable interpretation of backslash escapes'):

$ echo -e ' \t ' | hexdump -C
00000000  20 09 20 0a                                       | . .|
Chris Maes
  • 35,025
  • 12
  • 111
  • 136
Johannes Weiss
  • 52,533
  • 16
  • 102
  • 136
  • 1
    Thanks Johannes. You helped me find this solution : res='\t\t'x; echo -e '['$res']' – kalyanji Feb 08 '09 at 15:12
  • 2
    Do you happen to know, why `echo -e` does not work from Makefiles? – dma_k Oct 17 '10 at 00:01
  • 32
    That's because `echo -e` is not POSIX and `make` calls `/bin/sh` which is normally not the program use use interactively, and normally hasn't `-e` implemented. For portability, use `printf '\t'` instead. – Jo So Oct 05 '12 at 19:02
  • 1
    In Darwin (macOS), the `man` page for the `echo` command does not mention the option `-e`. However, this option is accepted. – ePi272314 Jun 28 '19 at 14:28
95

Use printf, not echo.

There are multiple different versions of the echo command. There's /bin/echo (which may or may not be the GNU Coreutils version, depending on the system), and the echo command is built into most shells. Different versions have different ways (or no way) to specify or disable escapes for control characters.

printf, on the other hand, has much less variation. It can exist as a command, typically /bin/printf, and it's built into some shells (bash and zsh have it, tcsh and ksh don't), but the various versions are much more similar to each other than the different versions of echo are. And you don't have to remember command-line options (with a few exceptions; GNU Coreutils printf accepts --version and --help, and the built-in bash printf accepts -v var to store the output in a variable).

For your example:

res='           'x # res = "\t\tx"
printf '%s\n' "[$res]"

And now it's time for me to admit that echo will work just as well for the example you're asking about; you just need to put double quotes around the argument:

echo "[$res]"

as kmkaplan wrote (two and a half years ago, I just noticed!). The problem with your original commands:

res='           'x # res = "\t\tx"
echo '['$res']' # expect [\t\tx]

isn't with echo; it's that the shell replaced the tab with a space before echo ever saw it.

echo is fine for simple output, like echo hello world, but you should use printf whenever you want to do something more complex. You can get echo to work, but the resulting code is likely to fail when you run it with a different echo implementation or a different shell.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
  • 1
    I liked this one, it allows me to use the knowledge of printf and all the format specifiers. – Arun Mar 19 '13 at 00:16
  • @JezenThomas: It is not more upvoted because it answers the question in another way than requested. The question specifically mentions echo, and echo is not a verb but a command. – Paulo Neves May 04 '17 at 13:15
  • @PauloNeves: I'd say it's used as a verb in the question: "How do I **echo** one or more tab characters using a bash script?" – Keith Thompson May 04 '17 at 18:53
74

You can also try:

echo Hello$'\t'world.
jbatista
  • 2,747
  • 8
  • 30
  • 48
36

Put your string between double quotes:

echo "[$res]"
kmkaplan
  • 18,655
  • 4
  • 51
  • 65
27

From the bash man page:

Words of the form $'string' are treated specially. The word expands to string, with backslash-escaped characters replaced as specified by the ANSI C standard.

So you can do this:

echo $'hello\tworld'
esoriano
  • 477
  • 6
  • 6
27

you need to use -e flag for echo then you can

echo -e "\t\t x"
Learning
  • 8,029
  • 3
  • 35
  • 46
20

Use the verbatim keystroke, ^V (CTRL+V, C-v, whatever).

When you type ^V into the terminal (or in most Unix editors), the following character is taken verbatim. You can use this to type a literal tab character inside a string you are echoing.

Something like the following works:

echo "^V<tab>"     # CTRL+V, TAB

Bash docs (q.v., "quoted-insert")

quoted-insert (C-q, C-v) Add the next character that you type to the line verbatim. This is how to insert key sequences like C-q, for example.

side note: according to this, ALT+TAB should do the same thing, but we've all bound that sequence to window switching so we can't use it

tab-insert (M-TAB) Insert a tab character.

--

Note: you can use this strategy with all sorts of unusual characters. Like a carriage return:

echo "^V^M"        # CTRL+V, CTRL+M

This is because carriage return is ASCII 13, and M is the 13th letter of the alphabet, so when you type ^M, you get the 13th ASCII character. You can see it in action using ls^M, at an empty prompt, which will insert a carriage return, causing the prompt to act just like you hit return. When these characters are normally interpreted, verbatim gets you get the literal character.

rich remer
  • 3,407
  • 2
  • 34
  • 47
  • 1
    Wish I could give you more upvotes for this one. I didn't want to use a -e in my arguments in this case, and this works great. Thanks! – Aaron R. Feb 19 '18 at 18:18
  • "... most Unix editors"? Tried to enter this with both vi and emacs and it didn't give the desired results in either. – GreenMatt Jan 11 '19 at 15:18
  • That's soooo cool! And saved my day when trying to use `grep` for catching lines containing `tab` characters. – Joël Feb 11 '19 at 19:50
  • `echo "somthing^Vsomething" > file` outputs the text exactly as is to the file :-/ – Sam Sirry Mar 01 '23 at 03:23
12

Using echo to print values of variables is a common Bash pitfall. Reference link:

http://mywiki.wooledge.org/BashPitfalls#echo_.24foo

Sparhawk
  • 1,581
  • 1
  • 19
  • 29
Anonymous
  • 3,011
  • 4
  • 24
  • 23
  • Cool, I like the "BashPitfalls", great piece of material and ease a lot of pain from my daily work! – Jerry Tian Oct 27 '11 at 04:49
  • +1 because this is sooo true. But note that kalyanji string starts with a “[” and does not contain any “\”. – kmkaplan Nov 28 '12 at 00:38
2

If you want to use echo "a\tb" in a script, you run the script as:

# sh -e myscript.sh

Alternatively, you can give to myscript.sh the execution permission, and then run the script.

# chmod +x myscript.sh
# ./myscript.sh
apaderno
  • 28,547
  • 16
  • 75
  • 90
ATC
  • 29
  • 1
0
res="\t\tx"
echo -e "[${res}]"
yanghaogn
  • 833
  • 7
  • 15