[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: scp overwriting precaution?

On Wed, Feb 26, 2020 at 09:48:40PM -0600, Greg Marks wrote:
>    for file in "${@}"
>       do
>          files="$files $(pwd | sed 's/\/home\/<username1>/\/home\/<username0>/g')/\"$file\""
>       done
>    scp -T -p <username0>@[Server IP Address]:"$files" .

Complete and utter failure.

Actually, you got *one* thing right: you used "$@" correctly.  Everything
else you've got here is wrong.

You don't stuff a list of filenames into a string variable with spaces in
between them, and quotes around them.  That doesn't work.  Filenames may
contain spaces.  And quotes.  If you need to store a list of things
(especially filenames), you use an array variable.

You're also using scp, in a nontrivial context.  That's a recipe for
disaster.  Even the OpenSSH developers say so:


  "The scp protocol is outdated, inflexible and not readily fixed. We
  recommend the use of more modern protocols like sftp and rsync for
  file transfer instead."

Specifically, when you pass a string containing spaces and quotes and
other shell markup characters to the remote system using scp, the
results tend to go horribly wrong.  A shell of some kind on the remote
system will try to parse the string that scp passes to it, and, well,
bad things happen to good files.

You also used sed's s command, with pathnames containing slashes as
the pattern and replacement, but still chose to use / as the delimiter
for the s command.  You could have chosen ANY other delimiter, which
doesn't appear in your pattern or replacement, instead of slash.

Now, I can't quite grasp what the goal of the script is, because it's
got so many errors and obfuscations in it, but maybe you just want
to do this:

cd /somewhere || exit
rsync -av . /backup/
rsync -av . secretuser@secrethost:/destination/

Some variant of that is usually what people want, when they're writing
a backup script.  Trying to reverse engineer yours, we might get
something like:

cd /home/username1 || exit
rsync -av . secretuser@secrethost:/home/username0/

And that's it.  There's no need to pull absolute pathnames into memory
and perform substitutions on them.  Just pass relative pathnames, from
the correct starting point, to the correct destination point.

Reply to: