Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

These work,

ssh remote 'echo hi > hi.txt'
echo hi | ssh remote 'cat > hi.txt'

but this does not work

ssh remote sh -c 'echo hi > hi.txt'

I expected to produce a file on remote named hi.txt containing "hi". Instead I get an empty file named hi.txt.

The following gives the expected behavior if executed from an interactive ssh session.

sh -c 'echo hi > hi.txt'

What do I miscomprehend about ssh and redirection?

share|improve this question
up vote 3 down vote accepted

I think your local shell is stripping off your quotes. You could try

ssh remote sh -c '"echo hi > hi.txt"'

When you send remote commands with ssh there are two shells involved with the reading of each line sent. Your local shell and your remote shell.

A good explanation of this can be found at Unix/Linux Shell Quoting for remote shells

share|improve this answer
oh wow, d'oh, this seemed so incomprehensible just a second ago, thanks – Praxeolitic Aug 14 '14 at 2:59

This is probably the single most confusing, and annoying thing when working with ssh (at least in my opinion).

The reason for this behavior is that ssh does not preserve arguments when executing a remote command. It takes all your arguments, and concatenates them together separated by spaces.

So when you run

ssh remote sh -c 'echo hi > hi.txt'

In effect, what you're running is:

ssh remote 'sh -c echo hi > hi.txt'

This runs sh -c echo, passes the shell (not echo) an argument of hi (which isn't used), and redirects the output to hi.txt.


The solution offered by chthonous (nested quoting) is one way to approach this. Lets look at it:

ssh remote sh -c '"echo hi > hi.txt"'

What's going on here is that ssh is concatenating all the arguments, so you effectively end up with:

ssh remote 'sh -c "echo hi > hi.txt"'
share|improve this answer
Hmm, just to be sure, it's not quite ssh's fault, right? Or at least, ssh can't do anything about this. The shell passes it arguments as arg[0]="sh", arg[1]="-c", arg[2]="echo hi > hi.txt". ssh can't know what these might mean to the shell on the remote so it can only concatenate all 3 and send that string to the remote shell to be interpreted. Chaos and confusion ensue. – Praxeolitic Aug 14 '14 at 3:34

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.