I need to copy a file from remote host to my local directory using scm where a file have spaces, for not I fixed the issue by ssh to that host and scp the file back. But I want to know how to copy that file, for instance there may be a case when local host don't have sshd installed.

I've try this:

scp kuba@\ that\ have\ spaces.txt ~/download/

but got error:

scp: /home/kuba/Pobrane/file: No such file or directory
scp: that: No such file or directory
scp: have: No such file or directory
scp: spaces.txt: No such file or directory

I've also try file\\ that\\ have\\ spaces.txt and file%20that%20have%20spaces.txt


SSH invokes a shell on the server (there's no way to bypass that). Scp calls this shell and tells it the names of the files that need to be written. The way scp is designed is to interpolate whatever you pass as a file name directly into the remote shell command. This means that if you have any shell special characters in file names, which for typical Unix shells means whitespace and !"#$&'()*-;<=>?@[\]^`{|}~ (some of these depend on the shell and position in the name), you need to quote them twice: once for the local shell and once for the remote shell.

This has advantages, in particular it allows you to specify wildcards. It's also what lets you use ~ for the remote home directory (but file names are relative to the remote home directory, so you could just use kuba@… instead of kuba@…). But the downside is that you need to take care when the file names do contain special characters. You also need to take care if you want to filter allowed file names on the server (especially for a restricted account that doesn't have shell command privileges).

The easy way of quoting twice is to use single quotes around the whole name, and a backslash before every special character that needs to be protected on the remote side. That doesn't work for single quotes in the file name; escape those as the four characters'\''. In your example:

scp 'kuba@\ that\ have\ spaces.txt' ~/download/

Your attempt with two backslashes didn't work because \\ is parsed by the local shell as backslash followed by a space that separates arguments; you need to send backslash-space to the remote host, and both the backslash and the space need to be protected from parsing by the local shell, so both need a backslash before them, i.e. you need 3 backslashes and a space.

scp kuba@\\\ that\\\ have\\\ spaces.txt ~/download/

SFTP doesn't go through a shell, so it's a way to avoid problems with special characters. SSHFS builds on SFTP and provides direct remote file access, so you can do

mkdir remote
sshfs kuba@ remote
cp remote/download/file\ that\ have\ spaces.txt ~/download/
fusermount -u remote
rmdir remote

The solution is to use both quotes and escaped space:

scp "kuba@\ that\ have\ spaces.txt" ~/download/

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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