Skip to content

Instantly share code, notes, and snippets.

@XanClic
Last active January 20, 2016 22:14
Show Gist options
  • Save XanClic/815362e5832d9cbb72dc to your computer and use it in GitHub Desktop.
Save XanClic/815362e5832d9cbb72dc to your computer and use it in GitHub Desktop.
#!/usr/bin/env ruby
# coding: utf-8
require 'shellwords'
PARALLEL_COPY = '~/bin/parallel-ssh-copy.rb'
def die(msg)
$stderr.puts(msg)
exit 1
end
if ARGV[0] && ARGV[0][0] == '-'
connections = ARGV.shift[1..-1].to_i
end
connections = 24 if !connections || connections <= 0
remote_path = ARGV[0]
local_path = ARGV[1] || '.'
if !remote_path || ['-h', '--help'].include?(remote_path)
die('Usage: recursive-ssh-copy ' +
'[-<connection count>] <remote path> [local path]')
end
rsplit = remote_path.split(':')
if rsplit.size < 2
die("#{remote_path} is not a valid remote path (colon missing)")
end
remote_server = rsplit.shift
remote_path = rsplit * ':'
die("#{local_path} is not a directory") if !File.directory?(local_path)
dirs = `ssh #{remote_server.shellescape} #{('find ' +
remote_path.shellescape + ' ' +
'-type d -print0').shellescape}` \
.split("\0")
die("No remote directory #{remote_path}") if dirs.empty?
rp_dir = File.dirname(remote_path) + '/'
dirs.each do |d|
dp = "#{local_path}/#{d.sub(rp_dir, '')}"
die("Failed to create #{d}") unless system("mkdir -p #{dp.shellescape}")
end
files = `ssh #{remote_server.shellescape} #{('find ' +
remote_path.shellescape + ' ' +
'-type f -print0').shellescape}` \
.split("\0")
files.sort.each_with_index do |f, i|
puts
puts "=> #{f.sub(rp_dir, '')} (#{i + 1} / #{files.size})"
puts
fp = "#{local_path}/#{f.sub(rp_dir, '')}"
system("#{PARALLEL_COPY} -#{connections} " +
(remote_server + ':' + f).shellescape + ' ' +
fp.shellescape)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment