-1

I'm writing a bash script to copy files from my local machine to a remote server using rsync. There is a space in the folder name "local folder" on my local machine; I don't know if this makes any difference.

If I write it as plain text it works:

rsync -arv  --filter=":- .gitignore" /local\ folder/path/ user@123.4.5.6:~/

I want to put the source and destination paths as variables, but I can't get it to work. The first thing I tried is this:

SOURCE="/local\ folder/path/"
DESTINATION="user@123.4.5.6:~/"
rsync -arv  --filter=":- .gitignore" $SOURCE $DESTINATION

I see this error:

rsync: change_dir "/local folder/path//~" failed: No such file or directory (2)

It seems to be a) running source and destination together, and b) not seeing the server address.

I've tried a number of variations, including braces:

rsync -arv  --filter=":- .gitignore" ${SOURCE} ${DESTINATION}

Using quotes:

rsync -arv  --filter=":- .gitignore" "${SOURCE}" "${DESTINATION}"

and putting the options into an array:

OPTIONS=( --protect-args -arv --filter=":- .gitignore")
rsync "${OPTIONS[@]}" ${SOURCE} ${DESTINATION}

I have also tried this after checking it in https://www.shellcheck.net/

#!/bin/bash

SOURCE="/folder name/path"
DESTINATION=user@123.4.5.6:~/

rsync -arv  --filter=":- .gitignore" "$SOURCE" $DESTINATION

and also:

#!/bin/bash

SOURCE="/folder\ name/path"
DESTINATION=user@123.4.5.6:~/

rsync -arv  --filter=":- .gitignore" "$SOURCE" $DESTINATION

Each time I get the same error. What simple thing am I missing here? I've looked at various examples including:

https://www.redpill-linpro.com/sysadvent/2015/12/03/rsync-tricks.html https://serverfault.com/questions/354112/rsync-and-bash-command-substitution

The space isn't the issue, or at least not the only issue. I've tried using double quotes around my variable names as suggested here

Thanks!

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
Little Brain
  • 2,647
  • 1
  • 30
  • 54
  • The code you provided produces [three Shellcheck findings](https://pastebin.com/8HRkX76M). Also see [How to use Shellcheck](http://github.com/koalaman/shellcheck), [How to debug a bash script?](http://unix.stackexchange.com/q/155551/56041) (U&L.SE), [How to debug a bash script?](http://stackoverflow.com/q/951336/608639) (SO), [How to debug bash script?](http://askubuntu.com/q/21136) (AskU), [Debugging Bash scripts](http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_02_03.html), etc. – jww May 04 '19 at 19:31
  • 1
    Quotes matter. `"$SOURCE"` -- as http://shellcheck.net/ will tell you in linking to [SC2086](https://github.com/koalaman/shellcheck/wiki/SC2086). – Charles Duffy May 04 '19 at 19:32
  • 1
    (Not that using all-caps names for your own variables is good form in the first place -- POSIX restricts the OS and built-in, POSIX-specified utilities to using only all-caps names for their own uses, reserving lowercase names for applications to use without creating unintentional conflicts). See https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html, fourth paragraph, keeping in mind that shell and environment variables share a single namespace. – Charles Duffy May 04 '19 at 19:33
  • Thanks for the suggestions, but nothing has worked so far. I am not sure the space is the problem. Why isn't the remote server name showing up in the error? – Little Brain May 04 '19 at 19:52
  • @CharlesDuffy, I have found the answer now but I don't seem to be able to post it. Is this because the question has been marked as a duplicate? It seems the tilde in the destination was also a problem, and I needed to quote that path also. – Little Brain May 04 '19 at 20:03
  • We have a separate duplicate question (actually, several) for the tilde. I can add one of them to the duplicate list. – Charles Duffy May 04 '19 at 20:10
  • 1
    (BTW, I take a slight bit of issue with characterization of that as "the" answer -- if you fix the quoting of the tilde but not the missing quotes on expansion, you'll still have `/local folder/` broken up into two arguments, `/local` and `folder/`). – Charles Duffy May 04 '19 at 20:13
  • Thank you. I've added an edit to the question explaining the different issues - tilde on local and remote paths seem to need separate handling, which I don't quite follow still - I can see why $HOME didn't work on the remote but not why it was required locally. I've also noted that the space needed quotes. Yay three errors in one short script! Thank you for the help. – Little Brain May 04 '19 at 20:14
  • I'd also be interested to know why quotes seem to be required around "$SOURCE" but not "$DESTINATION"? – Little Brain May 04 '19 at 20:21
  • Your destination doesn't have spaces. If it did, you'd see immediate problems without them there too. That said, it's dangerous in shell to take an attitude of "works when I test it, so must be okay". I've personally seen major data loss events caused by shell scripts that appeared to work just fine until encountering unusual filenames or other unexpected conditions. Run your code through http://shellcheck.net/, and fix what it finds unless you have a specific, well-understood reason not to *before* deploying scripts to production. – Charles Duffy May 05 '19 at 02:21
  • ...even without spaces, there are circumstances where leaving `$DESTINATION` unquoted will cause your code to break -- say somewhere earlier in your script you're parsing or generated `:`-separated content and set `IFS=:`; that'll cause the unquoted expansion to split into multiple arguments on colons. Or if you set `nullglob` or `failglob` and there's content in the name that can be interpreted as a glob expression. – Charles Duffy May 05 '19 at 02:25
  • Also you **can** use the tilde, if you leave that character unquoted: `source=~/"folder name/path"` is perfectly fine. Though `source="$HOME/folder name/path"` is even better. – Charles Duffy May 05 '19 at 02:26
  • As for why the tilde in the destination is allowed inside the quoted string, that's because it's interpreted by the *remote* system's shell. Quoting it locally prevents it from being expanded by the local shell, ensuring that it gets to the remote system. – Charles Duffy May 05 '19 at 02:27
  • BTW, see [What should I do when the answer of a (closed) question is added to the question itself?](https://meta.stackoverflow.com/questions/377643/what-should-i-do-when-the-answer-of-a-closed-question-is-added-to-the-question) on [meta] to understand the rollback. – Charles Duffy May 05 '19 at 02:28

1 Answers1

0

You need to quote your Variables: Try

rsync -arv  --filter=":- .gitignore" "$SOURCE" "$DESTINATION"
Eugen Rieck
  • 64,175
  • 10
  • 70
  • 92
  • NMDV, but note the "Answer Well-Asked Questions" section in [How to Answer](https://stackoverflow.com/help/how-to-answer), and the bullet point therein regarding questions which "have already been asked and answered many times before". – Charles Duffy May 04 '19 at 19:36
  • Thanks, I have tried adding quotes, which hasn't made any difference. I've noted the extra things I've tried in the question. – Little Brain May 04 '19 at 19:53