Created attachment 15076 [details] For cmd 'rsync "$UNSET_VAR" --debug=ALL5 --verbose --recursive -- /data/src/ /data/dest/' Hi! It's my first bug report here so let me know if I should clarify anything! If you add empty quotes to the rsync command line, it is interpreted as the current working directory ("."), and added to the SRC args. It doesn't matter if the quotes come before or after any options, if it comes before "--" or if there are other source directories specified. This is a problem if you specify quoted bash variables on the command line and one of them happens to be unset. /data/cwd $ ls file-i-dont-want-to-copy.txt /data/cwd $ rsync "$UNSET_VAR" --recursive --verbose -- /data/src/ /data/dest/ sending incremental file list file-i-dont-want-to-copy.txt file-i-want-to-copy.jpg sent 819,001 bytes received 54 bytes 1,638,110.00 bytes/sec total size is 818,581 speedup is 1.00 I have attached the output of the command with '--debug=ALL5' added, if it helps.
It probably wouldn't be difficult to spot the case you've identified and change the behaviour; I suspect you'd just need to change this code around line 2134 of flist.c, in send_file_list() to handle the case of (!len) separately (e.g. error, or ignore): len = strlen(fbuf); if (relative_paths) { /* We clean up fbuf below. */ name_type = NORMAL_NAME; >>>> } else if (!len || fbuf[len - 1] == '/') { if (len == 2 && fbuf[0] == '.') { /* Turn "./" into just "." rather than "./." */ fbuf[--len] = '\0'; } else { if (len + 1 >= MAXPATHLEN) overflow_exit("send_file_list"); fbuf[len++] = '.'; fbuf[len] = '\0'; } name_type = DOTDIR_NAME; } else if (len > 1 && fbuf[len-1] == '.' && fbuf[len-2] == '.' BUT there are other parts of the code that have already processed the arglist and in some cases rewritten it, and argpath parsing is already pretty complicated, because of handling lots of different cases (local or remote source(s), local or remote target, different syntaxes (rsync://host[/path], [host:]path, host::module[/path]), etc). In particular, an empty pathname part when accessing a daemon-defined module will already have been rewritten as ".", and since this is a useful (and probably widely-used) case, you wouldn't want to change that. In which case, you would have to accept an inconsistency between daemon (module) access, where empty does (and should) mean "." and non-daemon mode, where you want it rejected. As a simple workaround, consider using the shell syntax "${VAR?}" which will cause a shell error exit if the variable is unset -- which will make the problem obvious and reasonably easy to debug. $ rsync -aSHAXuvn "${VAR?}" ~/bin/ /tmp/ bash: VAR: parameter null or not set Or ${VAR:+"$VAR"}"${VAR:-mydefault}" which will insert VAR if set, or the default of your choice in the event that VAR is somehow unset. Depending on what outcome you want, you could set it to a flag that rsync doesn't recognise, and then rsync will complain about the command line: $ rsync -aSHAXuvn ${VAR:+"$VAR"}"${VAR:---VAR-unset}" ~/bin/ /tmp/ rsync: --VAR-unset: unknown option rsync error: syntax or usage error (code 1) at main.c(1572) [client=3.1.1] If the chosen default is a path that doesn't exist you'll get a nonfatal error from rsync, but any other files you intended to copy will still get copied. rsync -aSHAXuvn ${VAR:+"$VAR"}"${VAR:-./nosuchfile}" ~/bin/ /tmp/ sending incremental file list rsync: link_stat "./nosuchfile" failed: No such file or directory (2) ./ [...] sent 2,587 bytes received 873 bytes 6,920.00 bytes/sec total size is 791,762 speedup is 228.83 (DRY RUN) rsync error: some files/attrs were not transferred (see previous errors) (code 23) at main.c(1183) [sender=3.1.1] Hope this helps, Dave
While I also agree that you want to build in unset-var safety into your scripts (I a zsh option set that makes all unset vars fatal, for instance), I do also agree that specifying a totally empty arg to rsync is not useful, so I made rsync complain about it. This doesn't change an arg such as "host:" implying the home directory, so it won't help to safeguard a "$HOST:$DIR" expansion.