139

I am trying to rsync from one server to another. The servers have the same directory structure but I am having trouble getting the remotes server to properly recognize the path name on the remote when there is a space in it.

Here are the details

The local directory is

mnt/xlses/split/v2/name with space

The remote directory is

mnt/xlses/split/v2/name with space

I have tried everything I can find the latest attempt was

rsync --size-only -avzPe ssh  /mnt/xlses/split/v2/name\ with\ space/ root@myserver.com:/mnt/xlses/split/v2/"name with space"

when that runs the first thing it reports is that it is creating a new directory

I interrupt it and see that there is a new directory

mnt/xlses/split/v2/name

all of my files are in that directory

I was expecting them to be in

mnt/xlses/split/v2/name with space
Rui F Ribeiro
  • 56,709
  • 26
  • 150
  • 232
PyNEwbie
  • 1,569

12 Answers12

215

Try

rsync -s --size-only -avzPe ssh  "/mnt/xlses/split/v2/name with space/" "root@myserver.com:/mnt/xlses/split/v2/name with space"

From man rsync (updated 2023):

--secluded-args, -s

This option sends all filenames and most options to the remote rsync via the protocol (not the remote shell command line) which avoids letting the remote shell modify them. Wildcards are expanded on the remote host by rsync instead of a shell.

[...]

This option used to be called --protect-args (before 3.2.6) and that older name can still be used (though specifying it as -s is always the easiest and most compatible choice).

johnLate
  • 3,034
  • 23
    This doesn't work for Mac. – Matt Alexander Sep 25 '14 at 21:33
  • 13
    Works on the Mac if you install a recent version of rsync using home-brew. – Adriaan Tijsseling Feb 09 '15 at 16:17
  • 6
    See if it's in your version of rsync by running man rsync and searching (/s) for "--protect". To install with homebrew: brew install homebrew/dupes/rsync If not found run brew search rsync. – MikeiLL Jun 01 '15 at 17:08
  • 38
    New version install is unnecessary, you just escape spaces AND quote the host/filename - e.g. rsync -Pavuz 'you@host:~/file\ with\ spaces' ./ – ocodo Dec 11 '15 at 09:33
  • 1
    rsync: --protect-args: unknown option – Code42 Oct 21 '19 at 20:36
  • @ocodo Escaping spaces and commenting path (both single and double) does not work when rsyncing on Linux to receive files from MacOS (Big Sur). – Lexible Nov 20 '21 at 19:19
  • @Lexible - checked, it works for me. Without fully specifying the command line you used, I can't give you any other helpful info. (other than single and double quotes work differently.) But the answer here is the best one. – ocodo Dec 15 '21 at 02:36
  • In my case I was using variables to represent the source and destination directories => $SOURCE, $TARGET. I had to enclose these in quotes as well. – chribonn Jan 04 '23 at 14:30
  • 1
    The settings has been renamed to --secluded-args, -s in rsync 3.2.6. See man rsync . – user598527 Jun 08 '23 at 10:42
  • 1
    Coming at this very late but @ocodo's 2015 comment just saved my hash after HOURS of fruitless googling. Single-quote AND escape space in target, just escape spaces in source, and bam, it finally worked between two macs over SSH. Prior to that... failed without error. Looked like it succeeded but the files simply never appeared on the target. – John Smith Jul 04 '23 at 08:49
67

This works in bash: Escape the spaces with backslash and then use quotes:

rsync -avuz me@some.server.com:"/media/Music/Heavy\ Metal/Witch\ Mountain/*" .

Or if you have the path in the variable $remote_path, spaces can be escaped with substitution:

rsync -avuz me@some.server.com:"${remote_path// /\\ }" .
mpalvig
  • 43
teekarna
  • 795
  • 7
    Double-escaping is a pain, the -s option works on any modern version of rsync and is designed to solve this problem – Mark K Cowan Jul 23 '16 at 21:14
  • Note: if you're copying from a remote server with a space in path to a local path with space, you only need to add the quotes to the remote path. – lenooh Oct 02 '18 at 14:46
  • Solution from @teekarna worked for me. As per "rsync" man page, alternate is to use "--protect-args" or "-s" -- that too worked for me. – Kishan Parekh Oct 02 '19 at 10:26
  • 1
    this is the only solution for remote in Mac with macOS Catalina and rsync 3.1.3 (-s gives 'unknown option' ) – Pablo Marin-Garcia Sep 13 '21 at 21:53
  • Does not work when rsyncing on Linux to receive files from MacOS (Big Sur). – Lexible Nov 20 '21 at 19:20
42

Use two pairs of quotes

  1. Don't bother with all the backslashes, just use single quotes inside double quotes:

    ssh me@myserver.com:"'/home/me/test file'" .

  2. (recommended) You can also use the reverse, that is, double quotes inside single quotes:

    ssh me@myserver.com:'"/home/me/test file"' .

The 2nd one is better because you can then use wildcards on the server (because the single quotes will not get expanded on the client). I do this when trying to rsync multiple files with the same prefix.


Further info

Wildcards on the server side

If you want a * to be interpreted on the server rather than the client, the * must come inside just one of the 2 pairs of quotes. I find this counter-intuitive because logically the outer pair of quotes escapes the client interpretation, while the inner pair of quotes escapes the server interpretation.

Protect Args

The advantage, compared to the --protect-args solution, is that you actually do not have the restrictions of the --protect-args, so you can use special characters such as ~ or $. So you can write:

rsync host:'"$HOME/test file"' .

or

rsync host:'~"/test file"' .

Note that the tilde (~) in the latter example needs to be outside the double quotes.

You can put one of the pairs of quotes around the entire username@host:file part (e.g. ssh "me@myserver.com:'/home/me/test file'" .)

Sridhar Sarnobat
  • 1,802
  • 20
  • 27
  • Actually your suggestion of not putting the host part in quotes at all is more insightful so it's tempting to make this the first line in the post. – Sridhar Sarnobat Jun 29 '18 at 00:26
  • When you think about it, the 2 pairs of quotes are completely logical: the outer pair of quotes is so that the client treats it indivisibly (the contents of which are passed to the server verbatim) and the inner pair of quotes is for the server to recognize the indivisibility. – Sridhar Sarnobat Oct 12 '18 at 21:16
  • it works.. sometimes ... but you can defined :'...' on both local url and remote url ... so it would work for one or the other .. not both ... – mjs Nov 07 '19 at 19:48
  • Does not work when rsyncing on Linux to receive files from MacOS (Big Sur). – Lexible Nov 20 '21 at 19:20
7

Try

rsync --size-only -avzPe ssh /mnt/xlses/split/v2/name\ with\ space root@myserver.com:/mnt/xlses/split/v2/

I took off the trailing slash / from the source directory path. This will make rsync copy the directory and all its contents, which means rsync will worry about getting the name correct on the remote host (which it will) instead of you.

dg99
  • 2,642
6

I understand this is a old question, but I thought I would add to the existing body of knowledge.

I have used rsync with multiple folders with space and this works. I have folders numbered from 1-10 as follows:

  • The\ Folder1
  • The\ Folder2
  • The\ Folder3
  • ..
  • The\ Folder10

The 2 instances you would want to use rsync is local and remote.

  1. Local - Note the lack of quotes.

    rsync -avu /media/data/The\ Folder* .
    
  2. Remote - Note the presence of quotes

    rsync -avu -e ssh you@domain.com:"/media/data/The\ Folder*" .
    
techraf
  • 5,941
4

From the rsync manpages:

   If you need to transfer a filename  that  contains  whitespace,  you  can
   either  specify  the --protect-args (-s) option, or you'll need to escape
   the whitespace in a way that  the  remote  shell  will  understand.   For
   instance:

          rsync -av host:'file\ name\ with\ spaces' /dest
3

Generally speaking, quote the argument and escape the space characters in the argument. In the example you gave, try:

rsync --size-only -avzPe ssh  "/mnt/xlses/split/v2/name\ with\ space/" "root@myserver.com:/mnt/xlses/split/v2/name\ with\ space"
James
  • 31
1

On macOS I had to escape the first path normally, and the second path escaped + quotes. Example:

rsync -avhu VirtualBox\ VMs/Windows\ 10 bob@192.168.1.42:"/Users/bob/VirtualBox\ VMs/"

This is the only combination that worked with spaces on macOS. Both machines are macs.

lenooh
  • 131
  • I think you mean that the second path must be in quotes (not parentheses). This also worked for me to transfer from 1 Mac to another Mac – Mac471 Jan 04 '21 at 07:28
  • Mac471: you're right, it was a typo, fixed now! – lenooh Jan 04 '21 at 14:43
0

Well I am going to answer this question myself though someone else might do a better job of explaining it.

Evidently the setup on the destination machine affects how arguments are parsed and we must have something setup that is making it difficult to use quotes or slashes to escape spaces but we can use wild cards so I did this

rsync --size-only -avzPe ssh  /mnt/xlses/split/v2/name\ with\ space/ root@myserver.com:/mnt/xlses/split/v2/name*

This works for me because there is only one directory that begins with name if I had multiple directories this would not work.

Ultimately I need to understand how to setup the remote server so that it can parse the path name more efficiently - I never use spaces in directory names but the person who set this up did and at least for now I am stuck

PyNEwbie
  • 1,569
  • Your proposal only works because you already created the destination directory during your first (unsuccessful) attempt. See my answer for an easier way (that also has the advantage of not relying on a failed first attempt :). – dg99 Dec 10 '13 at 23:02
  • Well actually the directory already existed. You are not correct in my failed attempt it created the directory /~/name not /~/name with Space I deleted /~/name and kept trying different options The directory /~/name with space existed already I was trying to add files to it – PyNEwbie Dec 10 '13 at 23:21
  • Oh, I see what you mean. – dg99 Dec 11 '13 at 00:12
  • Works if you quote the host/path as well as escape the spaces. – ocodo Dec 11 '15 at 09:34
-1

Try this way:

find /path/ -exec rsync -A -X -av -r -s root@xxxx:/path/ {} \;
jherran
  • 3,939
-1

Depending on the situation, a quick option is to create a symlink on the remote system:

user@remote$ ln -s ~/name\ with\ space/ ~/name_with_space

Then use the -L flag in rsync which tells it to follow directory contents:

user@local$ rsync -avz -L user@remote:~/name_with_space/ ~/name\ with\ space
-1
rsync /mnt/xlses/split/v2/name\\\ with\\\ space/ root@myserver.com:/mnt/xlses/split/v2/name\\\ with\\\ space

double escape works too