38

I am using scp to copy a directory from one remote server to a new directory (IE just changing the name) on another remote server like:

scp -prq server1:dir1 server2:dir2

This works fine if dir2 does not exist on server2, it creates a new directory called dir2 which contains everything from dir1 on server1.

The problem comes when dir2 already exists on server2 (NOTE: I have no way of knowing this in advance or of doing a remove on dir2 on server2 beforehand) - what happens is I get a copy of dir1, called dir1, in dir2.

I am sure there is something basic I am missing, but I just cannot seem to work it out.

Any help much appreciated!

Regards,

Giles

Okay, I have less than 10 rep and cannot be ar$ed to wait 8 hrs so here is what I got:

Here is a script that works for me:

#!/bin/sh
echo "method 1"
scp -prq server1:dir1/* server2:dir2/ >/dev/null  2>&1

if [ "$?" -ne "0" ]; then
        echo "failed ... trying method 2"
        scp -prq server1:dir1 server2:dir2
fi

exit

Still not sure how to do this in a single command or even if possible.

Cheers @mindthemonkey, sometimes just getting a fresh viewpoint can help point the way.

5
  • you have scp access but not ssh?
    – Matt
    Sep 12, 2013 at 12:54
  • That is correct
    – Giles
    Sep 12, 2013 at 13:13
  • The only problem there is you will try the second copy on any failure, which is not necessarily dir2 not existing. Maybe if you can come up with a test that does virtually nothing (say copy a blank dir). Then based on the output either run scp1 or scp2
    – Matt
    Sep 12, 2013 at 13:50
  • Good point, I`ll keep that in mind going forward and repost if I come up with something.
    – Giles
    Sep 12, 2013 at 14:02
  • Can you sftp? then check the output of a cd dir2.
    – Matt
    Sep 12, 2013 at 14:13

4 Answers 4

43

Use this "dot" syntax:

scp -prq server1:dir1/. server2:dir2/

This copies the contents of that directory, rather than the directory itself. And I believe it's more portable than * globbing.

3
  • 7
    -p ⇒"Preserves modification times, access times, and modes from the original file." -r ⇒ "Recursively copy entire directories." -q ⇒ "Disables the progress meter." Source: computerhope.com/unix/scp.htm
    – kr85
    Mar 16, 2018 at 3:41
  • 17
    This gives me an error: scp: error: unexpected filename: . Apr 27, 2019 at 22:53
  • This may have been patched as of Nov 2018; I can't tell if this just applies to . or dir1/. as well: superuser.com/a/1403506/255506 May 3, 2022 at 16:26
2

Normally to control directory creation you need to use a trailing / to imply a complete path but I think this will then fail to create the directory if it doesn't exist:

scp -prq server1:dir1/* server2:dir2/

This could also miss hidden . files due to the * glob expansion (without some tricky shell specific work)

You can approach it differently with ssh and tar.

ssh server1 "cd dir1 && tar -cf - ." | ssh server2 "( mkdir -p dir2; cd dir2 && tar -xf - )"

But this means traffic goes via your local machine.

6
  • scp -prq server1:dir1/* server2:dir2/
    – Giles
    Sep 12, 2013 at 12:54
  • @Giles are you saying that does work?
    – Matt
    Sep 12, 2013 at 13:00
  • 1
    Odd, I edited that but it has got lost - no,that does not work, if the dir does not exist then scp gives an error. Also I do not have ssh available in this particular case (issue with user rights). This does give me an idea though, as I am doing this in a script I can try the above, capture any error and, on error, try the basic version from my first post. Thanks for the help @mindthemonkey
    – Giles
    Sep 12, 2013 at 13:12
  • 1
    It errors 'Is a directory' when the destination directory doesn't exist for me.
    – Matt
    Sep 12, 2013 at 13:16
  • 1
    Yes, me too, kind of an odd error given the directory does not exist.
    – Giles
    Sep 12, 2013 at 13:31
0

purge it using ssh first and then recreate it with scp. i.e. in a script file...

ssh -i ~/.ssh/[private_key] user@server2 "rm -rf dir2; exit;"

scp -prq server1:dir1 server2:dir2

0

I've banged my head against exactly this same issue, and what I ended up doing was semi-punting: if dir2 is [STUFF]/parent/child2, I rename or copy or link dir1 (as appropriate for the situation) to dir1_child2 on server1 so that its last path component is also child2, and then just execute

scp -prq server1:dir1_child2 server2:[STUFF]/parent

This runs whether or not child2 is present in dir2's parent directory, and happily replaces dir2 if it is.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .