2

I'm trying to move a file with rsync to a remote location,

The file has be be named : DRRS_(H264).mp4

but when I try :

rsync -azR output.mp4 user@server.com:encoded/somepath/DRRS_(H264).mp4

it says : bash: syntax error near unexpected token `('

But I don't get how I'm supposed to encapsulate this.

I tried :

rsync -azR output.mp4 user@server.com:"encoded/somepath/DRRS_(H264).mp4"

and

rsync -azR output.mp4 "user@server.com:encoded/somepath/DRRS_(H264).mp4"

without success.

7

You want to use the -s|--protect-args option to rsync.

Without it, the part after the : is passed as is to the remote shell so you can use constructs of that shell to build the list to transfer.

That way, if you know the remote shell is zsh for instance, you can do:

rsync host:'*(.)' there

to transfer only regular files. Or with csh/bash/zsh/ksh:

rsync host:'{foo,bar}.txt' there

Or:

rsync file 'host:"$HOME/$(uname)-file"'

Now, that means you can't easily transfer files with arbitrary name.

With -s, rsync doesn't pass the string to the remote shell. Instead, it passes it in-band to the rsync server on the remote host, so there's no interpretation by the remote shell.

( and ) being special for most shells, you'd have to escape it using the syntax of the remote shell, and that varies from shell to shell.

Best is to use -s instead.

rsync -sazR output.mp4 user@server.com:'encoded/somepath/DRRS_(H264).mp4'

However, rsync still performs (its own) globbing on the string you pass (even for the destination!). So you still can't pass arbitrary file names with rsync. If you want to process a file called * for instance, you need to escape it with backslash (at least, this time, that's irrespective of the remote shell).

rsync -sazR output.mp4 user@server.com:'\*'

So, to transfer a file with an arbitrary name contained in $1, you'll want to use:

file=$1
rsync_escaped_file=$(
  printf '%s.\n' "$file" | sed 's/[[*?]/\\&/g'
)
rsync_escaped_file=${rsync_escaped_file%.}
rsync -s ... "user@host:$rsync_escaped_file"

If your local shell is bash and you know the login shell of the remote user is also bash of the same version, alternatively, you can use printf %q to escape the characters that are special to the remote shell and not use -s:

LC_ALL=C printf -v shell_escaped_file %q "$1"
rsync ... "user@host:$shell_escaped_file"

If you know the login shell of the remote host is Bourne-like (Bourne, ksh, yash, zsh, bash, ash...) and your ssh client and server allows passing LC_* environment variables, you can also do (again, without -s):

LC_FILE=$1 rsync ... 'user@host:"$LC_FILE"'

Note1: the -s|--protect-args option is only available in version 3.0.0 (2008) or above

Note2: the rsync documentation warns that -s|--protect-args may become the default in future versions of rsync (so to be future-proof, you may want to start using --no-protect-args if you don't want its effect)

3

Try the below one, I tested this and it is working. You should quote your destination path with ' or " and you should escape the ( and ).

rsync -azR output.mp4 user@server.com:'encoded/somepath/DRRS_\(H264\).mp4'

UPDATE:

Call your script as below,

./sample.sh "encoded/somepath/DRRS_\(H264\).mp4"

sample.sh

 #!/bin/bash
 rsync -azR output.mp4 user@server.com:"$1"
  • somepath/DRRS_(H264).mp4 is inside $1 is there a way in bash to automatically escape? – Vincent Duprez Jul 21 '15 at 12:06
  • @VincentDuprez : Please find the updated answer and please do edit your question too. – Thushi Jul 21 '15 at 12:15
  • Note that it assumes the login shell of user on server.com is Bourne/csh/fish-like. It won't work if the login shell is rc for instance where backslash is not a quoting character. Best is to use -s|--protect-args instead here. – Stéphane Chazelas Jul 21 '15 at 12:29
2

You need to both quote the path and use a backslash to escape parentheses in the remote path.

Either single or double quotes will work.

rsync -azR output.mp4 user@server.com:"encoded/somepath/DRRS_\(H264\).mp4"

OR

rsync -azR output.mp4 user@server.com:'encoded/somepath/DRRS_\(H264\).mp4'

  • somepath/DRRS_(H264).mp4 is inside $1 is there a way in bash to automatically escape? – Vincent Duprez Jul 21 '15 at 12:06
  • That will only work if the login shell of the user on the remote host understands backslash as a quoting operator. Which will be the case in the majority of the cases, but would not be for instance if that shell is rc where the only quoting operator is single quote. Best is to use -s|--protect-args here to have a shell-agnostic solution. – Stéphane Chazelas Jul 21 '15 at 12:50

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.