0

I'm using the following:

filename="Test File 17-07-2020.xls"

sshpass -p $password ssh root@$IP /bin/bash -s "$filename" << 'EOF'

echo $1

EOF

This works when filename equals Testfile.xls and the echo outputs the full filename.

But fails if the filename is called Test File 17-07-2020.xls

My understanding is the spaces are breaking the input so it becomes:

$1 = Test
$2 = File
$3 = 17-07-2020.xls

Is there anyway to pass this keeping the spaces and having it all in $1

If I add filename=$(echo "$filename" | sed 's/ /\\ /g') before the SSHPASS command it does work.

Is that a valid way to do it or is there a better way ?

Thanks

2
  • echo "$1" shows 'Test' not the full name. Commented Jul 13, 2020 at 13:07
  • As a poor substitute in cases where you don't need that second argument you could maybe use "$*" instead of $1, but it isn't a very robust solution. Commented Jul 13, 2020 at 17:50

1 Answer 1

1

You still need to quote $1. Quoting the delimiter prevents $1 from being expanded early; it doesn't prevent word splitting once the shell actually executes echo $1.

sshpass -p $password ssh root@$IP "/bin/bash -s \"$filename\"" << 'EOF'

echo "$1"

EOF

If you are using bash locally, there are two extensions that could produce a value that is safe to pass to the remote shell.

sshpass -p $password ssh root@$IP "/bin/bash -s $(printf '%q' "$filename")"

or

sshpass -p $password ssh root@$IP "/bin/bash -s ${filename@Q}"

The former works at least in bash 3.2 (I highly doubt you are using an older version), while the latter requires bash 4.4.

Sign up to request clarification or add additional context in comments.

5 Comments

I've found this, but if the filename has spaces without the slashes then $1 only contains Test.
Oh, right, because the entire set of arguments is packaged as a single word by ssh to pass to the remote shell. I've fixed it to handle your case, but this still isn't robust: it will fail if $filename contains a double-quote itself.
You could swap the inner double quotes for single quotes ("/bin/bash -s '$filename'"), but that just shifts the problem to filenames containing single quotes.
How about ${filename@Q}?
Yeah, I was just playing around with that. printf '%q' "$filename" and "${filename@Q}" produce different output, so I was trying to convince myself either would work. (I might lean towards print "%q" ... as being more likely to be supported; @Q requires bash 4.4 or later.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.