This repository has been archived on 2023-02-21. You can view files and clone it, but cannot push or open issues or pull requests.
misc-csiraut/sftp_syncfiles

101 lines
3.8 KiB
Python
Executable File

#!/usr/bin/python3
import argparse
import cryptography
import glob
import os
import paramiko
import warnings
warnings.simplefilter("ignore", cryptography.utils.CryptographyDeprecationWarning)
def connection(hostname, username, password=None, keyfile=None):
if not keyfile:
keyfile = os.path.expanduser('~/.ssh/id_rsa')
key = paramiko.RSAKey.from_private_key_file(keyfile)
client = paramiko.SSHClient()
client.load_system_host_keys()
client.connect(hostname, username='csiraut', password=password, pkey=key)
return paramiko.SFTPClient.from_transport(client.get_transport())
def validate_local_path(path):
if not os.path.exists(path) or not os.path.isdir(path):
raise(Exception('Directory %s does not exist' % path))
def validate_remote_path(sftp, path):
lstat = sftp.lstat(path)
mode = oct(lstat.st_mode)[5]
if mode not in ['5', '7']:
raise(Exception('Remote path is not a folder or not writable'))
def parse_location(loc):
hostname, username, path = None, None, loc
if '@' in loc and ':' in loc:
username, remaning = loc.split('@')
hostname, path = remaning.split(':')
return hostname, username, path
def get(hostname, username, remotepath, localpath, password=None, keyfile=None):
validate_local_path(localpath)
sftp = connection(hostname, username, password=password, keyfile=keyfile)
validate_remote_path(sftp, remotepath)
dirlist = sftp.listdir_attr(remotepath)
filelist = [x.filename for x in dirlist if oct(x.st_mode)[5] not in ('5', '7')]
for f in filelist:
if args.verbose:
print('syncing %s to %s' % (remotepath, localpath))
remotefilepath = '%s/%s' % (remotepath, f)
localfilepath = '%s/%s' % (localpath, f)
sftp.get(remotefilepath, localfilepath)
if args.delete:
if args.verbose:
print('removing %s' % remotefilepath)
sftp.remove(remotefilepath)
def put(hostname, username, remotepath, localpath, password=None, keyfile=None):
validate_local_path(localpath)
sftp = connection(hostname, username, password=password, keyfile=keyfile)
validate_remote_path(sftp, remotepath)
filelist = [f for f in glob.glob('%s/*' % localpath) if not os.path.isdir(f)]
for f in filelist:
remotefilepath = '%s/%s' % (remotepath, f.split('/')[-1])
if args.verbose:
print('syncing %s to %s' % (f, remotefilepath))
sftp.put(f, remotefilepath)
if args.delete:
if args.verbose:
print('removing %s' % f)
os.remove(f)
def main(args):
orig = parse_location(args.origin)
dest = parse_location(args.destination)
if (orig[0] and dest[0]) or (not orig[1] and not dest[1]) or \
((orig[1] and '@' not in orig[1]) and (dest[1] and '@' not in dest[1])):
raise(Exception('Please provide one remote location like this: user@server:/path/to/direction'))
if orig[1]:
action, hostname, username, remotepath, localpath = 'get', orig[0], orig[1], orig[2], dest[2]
else:
action, hostname, username, remotepath, localpath = 'put', dest[0], dest[1], dest[2], orig[2]
globals()[action](hostname, username, remotepath, localpath, args.password, args.keyfile)
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='sftp.py — secure file transfer program')
parser.add_argument('origin', help='directory holding files to sync')
parser.add_argument('destination', help='target directory')
parser.add_argument('--keyfile')
parser.add_argument('--password')
parser.add_argument('--delete', action='store_true', help='remove source file(s) when transfered')
parser.add_argument('--verbose', action='store_true')
args = parser.parse_args()
main(args)