0

I need to escape single quotes in a variable.

ssh_command 'file=$(hostname)_server-setup_$(date +%Y-%m-%d).tar.gz && cd /var && tar -zcvf $file ini | wc -l | xargs printf \'Num files: %d, File: $file\''

I can surround the variable with double quotes but then the internal variables will be evaluated when the variable is declared, and that's not what I want.

ssh_command "file=$(hostname)_server-setup_$(date +%Y-%m-%d).tar.gz && cd /var && tar -zcvf $file ini | wc -l | xargs printf 'Num files: %d, File: $file'"

update

Have now come up with this, but then $file is just printed as $file

ssh_command (){
    ssh root@host $1
}

ssh_command 'file=$(hostname)_server-setup_$(date +%Y-%m-%d).tar.gz && cd /var && tar -zcvf $file ini | wc -l | xargs printf '"'"'Num files: %d, File: $file'"'"

output

Num files: 61, File: $file
clarkk
  • 27,151
  • 72
  • 200
  • 340
  • What is the desired output and what is the output you obtain now? what is the value of $file? – OscarAkaElvis Apr 23 '17 at 13:06
  • 4
    Possible duplicate of [How to escape single-quotes within single-quoted strings?](http://stackoverflow.com/questions/1250079/how-to-escape-single-quotes-within-single-quoted-strings) – e.dan Apr 23 '17 at 13:07
  • `$file` is declared in the command line in the beginning.. Output: `Num files: x, File: /path/to/tar` – clarkk Apr 23 '17 at 13:07
  • The correct answer is to use `'"'"'`. For the reason why, see the duplicate post comment. – e.dan Apr 23 '17 at 13:08
  • Have updated my question.. Have used the `'"'"'` but now `$file` is not set in the last part – clarkk Apr 23 '17 at 13:15
  • You can use ansi c style string if you don't want an unreadable mess of quotes. `$'\'string\''` – 123 Apr 23 '17 at 13:40
  • Possible canonical: *[How to escape the single quote character in an ssh / remote Bash command](https://stackoverflow.com/questions/20498599/how-to-escape-the-single-quote-character-in-an-ssh-remote-bash-command)* – Peter Mortensen Aug 16 '23 at 19:22

2 Answers2

4

When sending over a complicated command over SSH (using quotes, dollar signs, semi-colons), then I prefer to base64 encode/decode it. Here I've made base64_ssh.bash:

#!/bin/bash
script64=$(cat script.txt | base64 -w 0)
ssh 127.0.0.1 "echo $script64 | base64 -d | bash"

In the example above, simply put the command you would like to run on the remote server in script.txt, and then run the bash script.

This does require one extra file, but not having to escape quotes or other special characters makes this a better solution in my opinion.

This will also work with creating functions too.

The way it works, is it converts the command into a base64 encoded string which has a simpler character set (Wikipedia base64), and these characters will never need to be escaped. Then once it's on the other side, it is decoded and then piped through to the bash interpreter.

To make this work with your example above, put the following into script.txt:

file=$(hostname)_server-setup_$(date +%Y-%m-%d).tar.gz && cd /var && tar -zcvf $file ini | wc -l | xargs printf "Num files: %d, File: $file"
Robert Seaman
  • 2,432
  • 15
  • 18
3

For this not too big command I would not overcomplicate it and stick to the original double quotes, and escape just the $ which should not be expanded locally.

ssh_command "file=\$(hostname)_server-setup_$(date +%Y-%m-%d).tar.gz && cd /var && tar -zcvf \$file ini | wc -l | xargs printf 'Num files: %d, File: \$file'" 
ULick
  • 969
  • 6
  • 12