PuTTY – Pasting Text with Tabs into a Here-Document

bashclipboardhere-documentputtyssh

I have a string with tab delimited data that looks like:

h1  h2
a1  b1
a2  b2

I produced it with Notepad on Windows. I created tab delimited data, ensuring that tabs and not spaces are used.

enter image description here

I connect to a Linux server via SSH using PuTTY.
I would like to write the file to /tmp/test.txt and preserve the tabs.
So I run cat <<EOF >/tmp/test.txt. I copy the text from Notepad and paste it into the putty session. Then I enter EOF.

enter image description here

However, that produces a file without tabs having the contents of:

h1h2
a1b1
a2b2

I've found that this works:

sed 's/\\t/\t/g' > /tmp/test.txt << EOF
h1\th2
a1\tb1
a2\tb2
EOF

However, it required that I change my input string to use '\t' instead of actual tabs. What is a more elegant/simple solution that allows me to take a string literal as-is from Windows and write it into a file on the remote Linux machine?

I am SSHed into a Linux server from Windows via putty. The server is:

  • Distribution: Red Hat Enterprise Linux Server release 6.6 (Santiago)
  • Bash version: 4.1.2(1)-release (x86_64-redhat-linux-gnu)
  • cat: coreutils-8.4-37.0.1.el6.x86_64

Best Answer

When you type into a shell, the shell recognizes some characters as commands. For example, the carriage return character (the character sent by the Enter key) causes the shell to execute the command. The tab character causes the shell to perform completion. When you paste something into the PuTTY terminal window, from the shell's point of view, that's the same thing as if you'd typed these characters. So at the point the tab character is pasted, the shell performs completion, it doesn't insert a tab.

The easiest way to copy a file without it being transformed would be to use PuTTY's companion program PSCP or PSFTP to copy the file. This is the simplest way conceptually, but it does have the overhead of running another program, authenticating, choosing a directory, etc.

If you want something inline, you can paste directly into cat, rather than in a here document. Then you'd be pasting into the terminal's line editor, not into the shell's line editor. As the terminal's line editor is very primitive, only a few control characters have a special meaning there, not including tab. Press Ctrl+D at the beginning of a line to terminate the input.

[darkstar /]$ cat >text.txt
Paste
Ctrl+D
[darkstar /]$ 

I you want to transfer arbitrary data over a medium that interprets control characters, you can encode it into a form that uses only “tame” characters. Base64 is one; it doesn't use any control character and ignores whitespace and newlines. GNU coreutils, which is part of the basic installation on Linux and Cygwin, includes a base64 command. On the sender side, run base64 <file-to-decode, e.g.

  • On Windows: run base64 c:/path/to/test.txt from a Cygwin terminal
  • Copy the output.
  • In the shell in the PuTTY window, type `base64 -d >/tmp/test.txt and press Enter.
  • Paste the output from base64.
  • Press Ctrl+D.
Related Question