Bash - Escaping SSH commands

2019-04-29 07:02发布

I have a set of scripts that I use to download files via FTP and then delete them from the server.

It works as follows:

for dir in `ls /volume1/auto_downloads/sync-complete`
do
if [ "x$dir" != *"x"* ]
then
echo "DIR: $dir"

echo "Moving out of complete"
        # Soft delete from server so they don't get downloaded again
        ssh dan@172.19.1.15 mv -v "'/home/dan/Downloads/complete/$dir'" /home/dan/Downloads/downloaded

Now $dir could be "This is a file" which works fine.

The problem I'm having is with special characters eg:

  • "This is (a) file"
  • This is a file & stuff"

tend to error:

bash: -c: line 0: syntax error near unexpected token `('
bash: -c: line 0: `mv -v '/home/dan/Downloads/complete/This is (a) file' /home/dan/Downloads/downloaded'

I can't work out how to escape it so both the variable gets evaluated and the command gets escaped properly. I've tried various combinations of escape characters, literal quotes, normal quotes, etc

标签: bash ssh
4条回答
beautiful°
2楼-- · 2019-04-29 07:33

You need to quote the whole expression ssh user@host "command":

ssh dan@172.19.1.15 "mv -v /home/dan/Downloads/complete/$dir /home/dan/Downloads/downloaded"
查看更多
乱世女痞
3楼-- · 2019-04-29 07:35

I'm confused, because your code as written works for me:

> dir='foo & bar (and) baz'
> ssh host  mv -v "'/home/dan/Downloads/complete/$dir'" /home/dan/Downloads/downloaded
mv: cannot stat `/home/dan/Downloads/complete/foo & bar (and) baz': No such file or directory

For debugging, use set -vx at the top of the script to see what's going on.

查看更多
够拽才男人
4楼-- · 2019-04-29 07:36

If both sides are using bash, you can escape the arguments using printf '%q ', eg:

ssh dan@172.19.1.15 "$(printf '%q ' mv -v "/home/dan/Downloads/complete/$dir" /home/dan/Downloads/downloaded)"
查看更多
爷的心禁止访问
5楼-- · 2019-04-29 07:59

Will Palmer's suggestion of using printf is great but I think it makes more sense to put the literal parts in printf's format.

That way, multi-command one-liners are more intuitive to write:

ssh user@host "$(printf 'mkdir -p -- %q && cd -- "$_" && tar -zx' "$DIR")"
查看更多
登录 后发表回答