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/ [email protected]:/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

12 Answers 12

215

Try

rsync -s --size-only -avzPe ssh  "/mnt/xlses/split/v2/name with space/" "[email protected]:/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).

10
  • 23
    This doesn't work for Mac. Sep 25, 2014 at 21:33
  • 13
    Works on the Mac if you install a recent version of rsync using home-brew. Feb 9, 2015 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 1, 2015 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, 2015 at 9:33
  • 1
    rsync: --protect-args: unknown option
    – Code42
    Oct 21, 2019 at 20:36
67

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

rsync -avuz [email protected]:"/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 [email protected]:"${remote_path// /\\ }" .
5
  • 7
    Double-escaping is a pain, the -s option works on any modern version of rsync and is designed to solve this problem Jul 23, 2016 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 2, 2018 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. Oct 2, 2019 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' ) Sep 13, 2021 at 21:53
  • Does not work when rsyncing on Linux to receive files from MacOS (Big Sur).
    – Lexible
    Nov 20, 2021 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 [email protected]:"'/home/me/test file'" .

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

    ssh [email protected]:'"/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 "[email protected]:'/home/me/test file'" .)

4
  • 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. Jun 29, 2018 at 0: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. Oct 12, 2018 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 7, 2019 at 19:48
  • Does not work when rsyncing on Linux to receive files from MacOS (Big Sur).
    – Lexible
    Nov 20, 2021 at 19:20
7

Try

rsync --size-only -avzPe ssh /mnt/xlses/split/v2/name\ with\ space [email protected]:/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.

2
  • 9
    This doesn't explain how to deal with spaces on the remote side.
    – ckujau
    Sep 21, 2017 at 21:36
  • Does not work when rsyncing on Linux to receive files from MacOS (Big Sur).
    – Lexible
    Nov 20, 2021 at 19:22
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 [email protected]:"/media/data/The\ Folder*" .
    
1
  • Does not work when rsyncing on Linux to receive files from MacOS (Big Sur).
    – Lexible
    Nov 20, 2021 at 19:26
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
2
  • 1
    This syntax with \ also works fine for target folders on a Synology NAS with current v6.x DSM and rsync v3.0.9
    – PeterCo
    Jan 14, 2021 at 15:19
  • Does not work when rsyncing on Linux to receive files from MacOS (Big Sur).
    – Lexible
    Nov 20, 2021 at 19:29
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/" "[email protected]:/mnt/xlses/split/v2/name\ with\ space"
1

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

rsync -avhu VirtualBox\ VMs/Windows\ 10 [email protected]:"/Users/bob/VirtualBox\ VMs/"

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

2
  • 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 4, 2021 at 7:28
  • Mac471: you're right, it was a typo, fixed now!
    – lenooh
    Jan 4, 2021 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/ [email protected]:/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

4
  • 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, 2013 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, 2013 at 23:21
  • Oh, I see what you mean.
    – dg99
    Dec 11, 2013 at 0:12
  • Works if you quote the host/path as well as escape the spaces.
    – ocodo
    Dec 11, 2015 at 9:34
-1

Try this way:

find /path/ -exec rsync -A -X -av -r -s root@xxxx:/path/ {} \;
-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
  • I like the thinking, there are times when symlinking bypasses the hassle of bad naming or unnecessarily complex hierarchies. Jun 29, 2018 at 0:24
-1
rsync /mnt/xlses/split/v2/name\\\ with\\\ space/ [email protected]:/mnt/xlses/split/v2/name\\\ with\\\ space

double escape works too

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .