435

I want to copy a file from remote to local system. Now I'm using scp command in linux system. I have some folders or files names are with spaces, when I try to copy that file, it shows the error message: "No such file or directory".

I tried:

scp ael5105@192.168.0.200:'/home/5105/test/gg/Untitled Folder/a/qy.jpg' /var/www/try/

I saw the some reference online but I don't understand perfectly, can any one help on this?

how can I escape spaces in file name or directory names during copying...

starball
  • 20,030
  • 7
  • 43
  • 238
AlexPandiyan
  • 4,467
  • 2
  • 14
  • 11
  • Double check that the file really exists. Put the quotes around the whole path, including the login name and ip address. Alternatively, remote the quotes and prepend the space with a backslash instead. –  Nov 08 '13 at 12:30

13 Answers13

681

Basically you need to escape it twice, because it's escaped locally and then on the remote end.

There are a couple of options you can do (in bash):

scp user@example.com:"web/tmp/Master\ File\ 18\ 10\ 13.xls" .
scp user@example.com:web/tmp/Master\\\ File\\\ 18\\\ 10\\\ 13.xls .

Another option only works with older versions of OpenSSH and possibly other clients:

scp user@example.com:"'web/tmp/Master File 18 0 13.xls'" .
Daniel Santos
  • 3,098
  • 26
  • 25
Adrian Gunawan
  • 13,979
  • 11
  • 40
  • 41
  • 18
    This is pretty minor, but on a Mac and in most console apps like Terminal, there is a 'Paste Escaped Text' option. I therefore used the second option. – Sacrilicious Jul 26 '14 at 16:42
  • Here is a relevant question: http://stackoverflow.com/questions/5608112/escape-filenames-using-the-same-way-bash-do-it – Hamy Jan 04 '15 at 04:48
  • 15
    ' " path " ' worked while " ' path ' " failed; conclusion single quotes first and then the double quotes to surround –  Mar 25 '18 at 02:58
  • 8
    Wow! That's probably the single most ridiculous program behaviour I've seen! – jankes Apr 08 '18 at 08:21
  • 12
    @jankes It isn't without merits. The fact that what you put there is a shell command argument allows you to do stuff like `scp user@example.com:'$(ls -t | head -1)' .` to get the most recently created file in the server, or `scp user@example.com:'dir/*.{xml,pdf}' .` to get all xml and pdf files from a remote directory. In general, I prefer this over having convenience with files that have spaces. Files with spaces are always a bother. – JoL Jul 16 '18 at 16:55
  • 2
    why it is escape 2 times? any way to change this behavior? – Fractale Sep 30 '18 at 06:38
  • 3
    How does one know what shell is going to be used at the other end in order to know which quoting syntax to apply for the inner quoting? Should this method only be used in scripts where the script's author has control of the shell at the other end? – codeshot Aug 02 '19 at 17:29
  • 2
    scp user@example.com:"web/tmp/Master\ File\ 18\ 10\ 13.xls" . works – Klajd Deda Sep 09 '19 at 14:53
  • 1
    If you get a "protocol error: filename does not match request" error, you might want to add option `-T`. See https://stackoverflow.com/q/54598689/452614 – Ludovic Kuty Oct 22 '20 at 06:24
  • 1
    scp user@example.com:web/tmp/Master\\\ File\\\ 18\\\ 10\\\ 13.xls . it worked for me – Sanchi Girotra Feb 11 '21 at 10:49
  • 2
    I also had to add the -T flag to scp due to a protocol error: https://stackoverflow.com/q/54598689 – Christopher Shroba Nov 13 '21 at 16:00
  • @ChristopherShroba Thanks, I had to do the same. No combinations of quotes worked until I did that, though escaping spaces did work. (Using openssh-client 1:7.9p1-10 on Debian 11.) – Peter Hansen Sep 21 '22 at 14:43
104

works

scp localhost:"f/a\ b\ c" .

scp localhost:'f/a\ b\ c' .

does not work

scp localhost:'f/a b c' .

The reason is that the string is interpreted by the shell before the path is passed to the scp command. So when it gets to the remote the remote is looking for a string with unescaped quotes and it fails

To see this in action, start a shell with the -vx options ie bash -vx and it will display the interpolated version of the command as it runs it.

Navin
  • 3,681
  • 3
  • 28
  • 52
Vorsprung
  • 32,923
  • 5
  • 39
  • 63
  • 1
    Using single quotes and escaping worked for me but not double quotes – Mauricio Trajano Feb 15 '18 at 21:21
  • 1
    @MauricioTrajano take a look at https://www.gnu.org/software/bash/manual/html_node/Quoting.html all the quotes do different things. In the simple case above double ``"`` or single ``'`` work the same – Vorsprung Feb 15 '18 at 22:05
60

Use 3 backslashes to escape spaces in names of directories:

scp user@host:/path/to/directory\\\ with\\\ spaces/file ~/Downloads

should copy to your Downloads directory the file from the remote directory called directory with spaces.

Chris
  • 1,173
  • 11
  • 19
  • 2
    This is the only one that worked for me on Ubuntu 19.10. No double quotes, no soft and hard quotes in and out, no escaped quotes. Only tripplebackslashed spaces. Very weird. Thank you! – uldics Apr 21 '20 at 06:22
  • Mind blown. I've never even heard of using triple backslashes. This was the only thing that worked for me on Ubuntu 18. Can someone explain why and when this became necessary? And if it's only for scp or are there other situations you need to use triple backslashes instead of just the one? – Joshua Pinter Sep 25 '20 at 14:17
  • 2
    See [answer](https://stackoverflow.com/a/20364170/452614) by @AdrianGunawan. It is escaped once on the local host and then a second time on the remote host. So `\\\_` is escaped once to get `\_` and then it is escaped another time to get a space `_`. I used `_` to clearly represent a space. – Ludovic Kuty Oct 22 '20 at 06:03
52

Also you can do something like:

scp foo@bar:"\"apath/with spaces in it/\""

The first level of quotes will be interpreted by scp and then the second level of quotes will preserve the spaces.

MattK
  • 1,431
  • 13
  • 14
27

I encountered similar issues when trying to copy files from remote paths containing spaces using scp from within a Bash script.

Here are the solutions I came up with:

Escape paths manually:

scp user@host:'dir\ with\ spaces/file\ with\ spaces' <destination>
scp user@host:"dir\\ with\\ spaces/file\\ with\\ spaces" <destination>
scp user@host:dir\\\ with\\\ spaces/file\\\ with\\\ spaces <destination>

Note: does not require option -T (see below).

Use double-quoting + option -T:

scp -T user@host:"'path with spaces'" <destination>
scp -T user@host:'"path with spaces"' <destination>
scp -T user@host:"\"path with spaces\"" <destination>

Note: without option -T, these commands fail with protocol error: filename does not match request. The reason for this is discussed in detail here.

Escape path using Bash's printf:

source="path with spaces"
printf -v source "%q" "${source}"
scp user@host:"${source}" <destination>

One-liner for shell use:

source="path with spaces"; printf -v source "%q" "${source}"; scp user@host:"${source}" <destination>

Note: works fine without option -T.

Fonic
  • 2,625
  • 23
  • 20
  • 3
    Thank you for the printf solution. It's the only one that worked for me. I needed it for both source and destination. FYI, it's possible to put all in same line with ";" – Slim Aloui May 07 '22 at 17:43
  • 1
    @SlimAloui You're welcome. Good suggestion, I added a one-liner for the `printf` alternative. – Fonic May 08 '22 at 08:04
14

I had huge difficulty getting this to work for a shell variable containing a filename with whitespace. For some reason using:

file="foo bar/baz"
scp user@example.com:"'$file'"

as in @Adrian's answer seems to fail.

Turns out that what works best is using a parameter expansion to prepend backslashes to the whitespace as follows:

file="foo bar/baz"
file=${file// /\\ }
scp user@example.com:"$file"
Luke Davis
  • 2,548
  • 2
  • 21
  • 43
  • 1
    I would suggest the more robust 'substitute all' expansion: `file="${file//\ /\\\ }"` – troyfolger Dec 18 '17 at 01:17
  • Forgot about that distinction -- I'm rusty on my parameter expansions. Thanks! – Luke Davis Dec 18 '17 at 01:25
  • I didn't have a variable but this satisfied me as a good alternative to 3 backslashes for a path with a lot of spaces. No one has time for that! – Robert Dundon Dec 03 '18 at 20:10
  • Is there some reason that `${file//\ /\\\ }` is better than `${file// /\\ }`? Does that space need escaping for some reason? – opello Aug 11 '20 at 20:53
  • What if the path had a prefix like `/home/user/folder/` followed by the file with spaces? I have to enclose the whole thing with double quotes and escaping the one around the `$file` doesn't work. – Frak Aug 24 '20 at 19:39
  • 1
    @opello Nope, it was not necessary to escape the whitespace. Have fixed the answer. – Luke Davis Aug 26 '20 at 16:36
  • If you are really unlucky and have both backslashes and spaces in your filename, first escape the backslashes and then the spaces: `file=${file//\\/\\\\};file=${file// /\\ }` – cayhorstmann Mar 28 '21 at 05:11
  • For me (on ubuntu) it worked by putting the quotes within the variable: `export file='"foo bar/baz"' ; scp user@example.com:"$file"` . That way I can avoid the substitution. Maybe that is worth including in the answer. – Kjell May 17 '22 at 08:03
9

Sorry for using this Linux question to put this tip for Powershell on Windows 10: the space char escaping with backslashes or surrounding with quotes didn't work for me in this case. Not efficient, but I solved it using the "?" char instead:

for the file "tasks.txt Jun-22.bkp" I downloaded it using "tasks.txt?Jun-22.bkp"

9

scp ael5105@192.168.0.200:/home/5105/test/gg/Untitled?Folder/a/qy.jpg /var/www/try/

the ? does a glob on the remote and will match any character, including a space

Jayen
  • 5,653
  • 2
  • 44
  • 65
1

I'm new to Linux and I used Kali xD, here how's mine works: From your system to remote server if you want to transfer your file with single or multiple spaces:

$ scp this\ is\ my\ file tryhackme@1.1.1.1:/home/tryhackme

Note that the IP address is only example and the last I type is directory and the dollar sign which is the prompt, the code start with scp.

Also you can specifiy what name you want to that file when it is transfer, ex. /home/tryhackme/file1 or with single or multiple spaces like /home/tryhackme/"this\ is\ new\ file".

From remote server to your system, same as above with single or multiple spaces:

$ scp tryhackme@1.1.1.1:/home/tryhackme/"remote\ server\ file" "this is mine now"

Note that you only use backward slash \\ to the file you want to copy, as you can see that the string "this is mine now" has no \\ because that is the name of the file we want when it transfer to our system and not the file that we want to secure copy (scp). Sorry for my explanation, I hope someone will understand, I hope this helps to someone who needs another solution.

Obsidian
  • 3,719
  • 8
  • 17
  • 30
Yes But No
  • 11
  • 2
0

If the file or folder name is having space in between then you can simply add a black slash '' before the space and then put the whole path inside a single quotation ('') and it should work then.

Example:

Suppose the folder name is 'Test Folder' and it is inside /home/ in remote machine. Then you can access or download the folder using following scp command.

scp -r <user>@<host>:'/home/Test\ Folder' .
Ramyani
  • 1,019
  • 1
  • 9
  • 12
0

In linux-terminal or cmd if there is any space in path between word you must use quotation ('') ("") mark.

you should something like this :

$ '/home/tryhackme'

not

$ /home/tryhackme
0

Just stick wildcards in where the spaces should be: 'foo/bar*bar.txt'

Scooby
  • 1
  • 1
0

Try with the following

scp ael5105@192.168.0.200:"/home/5105/test/gg/Untitled\ Folder/a/qy.jpg" /var/www/try/

Here space before Folder is escaped with "\" (backslash) and the path is put under "(quote). Please also check if /var/www/try/ exists.

blueDexter
  • 977
  • 11
  • 14