I'm trying to move a file with rsync to a remote location, The file has be be named : DRRS_(H264).mp4but when I try : rsync -azR output.mp4 user@server.com:encoded/somepath/DRRS_(H264).mp4it 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).mp4andrsync -azR output.mp4 user@server.com:encoded/somepath/DRRS_(H264).mp4without success.
How to pass argument with char ( in remote path?
shell;rsync;quoting
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:'*(.)' thereto transfer only regular files. Or with csh/bash/zsh/ksh:rsync host:'{foo,bar}.txt' thereOr: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=$1rsync_escaped_file=$(  printf '%s.\n' $file | sed 's/[[*?]/\\&/g')rsync_escaped_file=${rsync_escaped_file%.}rsync -s ... user@host:$rsync_escaped_fileIf 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 $1rsync ... user@host:$shell_escaped_fileIf 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 aboveNote2: 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)