3

I am using the find command to locate files that need to be scp'd to a target host. My problem is that the directory structure is not maintained on the target.

cd /path/to/dir; find . -exec scp -pr {} hostname:/tmp/. \;

(I have tried this with and with -r.)

If find yields ./subdir/file, I would like for it to be copied to hostname:/tmp/subdir/file.

Oh, and before it's suggested, the remote host has disabled rsync.

Aaron Copley
  • 242
  • 3
  • 11
  • I'm assuming you're passing more options to `find` than you have shown in your question, since you could replace that entire command with `scp -pr /path/to/dir hostname:/tmp/.` – ThisSuitIsBlackNot Sep 06 '13 at 21:37
  • Sorry, yes, I am using `find` to look for very specific files. I did not think my pattern would do more than complicate the example. – Aaron Copley Sep 06 '13 at 21:39
  • 1
    If you have enough disk space you could use `tar` then `scp` the tarball to the remote host then untar. – Red Cricket Sep 06 '13 at 23:50

2 Answers2

4

You can do this with two separate commands. First you need to create the directories on the remote server where each file is

find . -type f -printf "%h\n" | sort | uniq | xargs -i ssh hostname mkdir -p /tmp/{}

Then you can copy each file as before

find . -type f -exec scp {} hostname:/tmp/{} \;
Aaron Okano
  • 2,243
  • 1
  • 12
  • 5
  • This looks like it should work the best. Thanks. Such a simple problem but it's been giving me a fit. The additional perspective helps. – Aaron Copley Sep 10 '13 at 13:27
1

You need something more complex than just find:

#!/bin/bash

remote=user@host:/path/to/dest/

for file in $(find . -type f); do
    echo scp $file ${remote}$(echo $file | sed 's:^\.*/::')
done

And you can always condense that down to:

for file in $(find . -type f); do echo scp $file user@host:/path/to/dest/$(echo $file | sed 's:^\.*/::'); done

Just remove the echo when you're sure that it will run as you expect.

Random example output:

scp ./cron/test.txt user@host:/path/to/dest/cron/test.txt
scp ./cron/spamproc/rfc822_addresses.php user@host:/path/to/dest/cron/spamproc/rfc822_addresses.php
scp ./cron/spamproc/mime_parser.php user@host:/path/to/dest/cron/spamproc/mime_parser.php
scp ./cron/spamproc/spamproc.php user@host:/path/to/dest/cron/spamproc/spamproc.php
scp ./cron/spamproc/class.imap.php user@host:/path/to/dest/cron/spamproc/class.imap.php
scp ./count_imap.sh user@host:/path/to/dest/count_imap.sh
Sammitch
  • 30,782
  • 7
  • 50
  • 77
  • `scp /path/to/file host:/path/to/file` fails if the directory `/path/to` does not already exist on `host`. – ThisSuitIsBlackNot Sep 06 '13 at 21:53
  • @ThisSuitIsBlackNot Hrmm... well unless you want to re-write a hefty portion of rsync I would suggest getting rsync turned on on the target server. – Sammitch Sep 06 '13 at 21:56
  • Thanks, this could be modified to work if the directory structure is created before hand. Unfortunately, I don't maintain the remote side. Rsync would be better for so many reasons. – Aaron Copley Sep 10 '13 at 13:25