python sftp 删除目录_使用paramiko的SFTP get或put整个目录

在《使用paramiko执行远程linux主机命令》中举例说明了执行远程linux主机命令的方法,其实paramiko还支持SFTP传输文件。

由于get或put方法每次只能传输一个文件,而不是整个目录,因此我们先看一下传输单个文件的方法,其实非常简单,网上也有很多参考资料了。

还是直接使用前文中定义的类,我们添加两个方法即可(本文中不需要使用的方法先用pass代替了):

1 #定义一个类,表示一台远端linux主机

2 classLinux(object):3 #通过IP, 用户名,密码,超时时间初始化一个远程Linux主机

4 def __init__(self, ip, username, password, timeout=30):5 self.ip =ip6 self.username =username7 self.password =password8 self.timeout =timeout9 #transport和chanel

10 self.t = ''

11 self.chan = ''

12 #链接失败的重试次数

13 self.try_times = 3

14

15 #调用该方法连接远程主机

16 defconnect(self):17 pass

18

19 #断开连接

20 defclose(self):21 pass

22

23 #发送要执行的命令

24 defsend(self, cmd):25 pass

26

27 #get单个文件

28 defsftp_get(self, remotefile, localfile):29 t = paramiko.Transport(sock=(self.ip, 22))30 t.connect(username=self.username, password=self.password)31 sftp =paramiko.SFTPClient.from_transport(t)32 sftp.get(remotefile, localfile)33 t.close()34

35 #put单个文件

36 defsftp_put(self, localfile, remotefile):37 t = paramiko.Transport(sock=(self.ip, 22))38 t.connect(username=self.username, password=self.password)39 sftp =paramiko.SFTPClient.from_transport(t)40 sftp.put(localfile, remotefile)41 t.close()

注意上面的remotefile, localfile一定是文件,不能是目录,对于sftp_get,localfile指定本地将要保存的文件名,可以与remotefile的名字不一样;

而sftp_put中,remotefile指定远端将要保存的文件名,可与localfile的名字不一样,测试代码如下:

1 if __name__ == '__main__':2 remotefile = r'/home/sea/test/xxoo.txt'

3 localfile = r'E:\PythonFiles\Learn\ooxx.txt'

4

5 host = Linux('192.168.180.128', 'root', '1234')6

7 #将远端的xxoo.txt get到本地,并保存为ooxx.txt

8 host.sftp_get(remotefile, localfile)9

10 ## 将本地的xxoo.txt put到远端,并保持为xxoo.txt

11 #host.sftp_put(localfile, remotefile)

下面再来考虑下如何传输整个目录?

有两种思路:

1 如果是要get则采用已经定义的connect方法连接到linux主机,然后通过send方法执行tar命令将需要传输的整个目录打包,再传输打包后的文件即可,如果是put则需在本地打包

该方法的缺点是:在远端或者本地进行打包或者解压,并且打包会占用临时存储空间,如果是远端打包还需先SSH链接linux主机。

优点是:不用做目录扫描处理。

2 遍历需要get或put的目录及其子目录,然后依次传输每一个文件。优点是不需要SSH登陆和打包解压,缺点是需要做目录扫描,但是目录扫描是很简单的,因此我们采用这种方法。

先来看看Get,由于要扫描目录,因此先定义一个方法用来对指定目录进行扫描,找出该目录及所有子目录中的所有文件。

那么问题来了,怎么扫描目录呢?使用python的os库的方法吗?肯定是不行的,因为python的os库的方法都是对本地目录或文件的操作,它是无法操作远程linux主机上的文件和目录的。

其实paramiko的SFTP接口提供了操作远端linux主机上的文件和目录的方法,只要建立了与远端的SFTP连接后,就可以执行文件和目录操作。

下面是获取远端linux主机上指定目录及其子目录下的所有文件的方法,也是定义在上面的类中的。

1 #------获取远端linux主机上指定目录及其子目录下的所有文件------

2 def __get_all_files_in_remote_dir(self, sftp, remote_dir):3 #保存所有文件的列表

4 all_files =list()5

6 #去掉路径字符串最后的字符'/',如果有的话

7 if remote_dir[-1] == '/':8 remote_dir = remote_dir[0:-1]9

10 #获取当前指定目录下的所有目录及文件,包含属性值

11 files =sftp.listdir_attr(remote_dir)12 for x infiles:13 #remote_dir目录中每一个文件或目录的完整路径

14 filename = remote_dir + '/' +x.filename15 #如果是目录,则递归处理该目录,这里用到了stat库中的S_ISDIR方法,与linux中的宏的名字完全一致

16 ifS_ISDIR(x.st_mode):17 all_files.extend(self.__get_all_files_in_remote_dir(sftp, filename))18 else:19 all_files.append(filename)20 return all_files

在上面的方法中,参数sftp表示已经建立的sftp连接,remote_dir是要扫描的远端目录。

在扫描目录的时候,使用的listdir_attr方法会列出指定目录下的所有文件或目录,并且还会列出其属性,比如st_size,st_uid,st_gid,st_mode,st_atime,st_mtime,

这些属性与linux中的stat函数返回的属性类似,我们就是根据其中的st_mode属性来判断是一个目录还是文件,并且处理st_mode的方法(位于stat模块中)也是与linux中定义的宏一致的。

获取到指定目录下的所有文件之后,传输就比较简单了,依次遍历get即可:

1 defsftp_get_dir(self, remote_dir, local_dir):2 t = paramiko.Transport(sock=(self.ip, 22))3 t.connect(username=self.username, password=self.password)4 sftp =paramiko.SFTPClient.from_transport(t)5

6 #获取远端linux主机上指定目录及其子目录下的所有文件

7 all_files = self.__get_all_files_in_remote_dir(sftp, remote_dir)8 #依次get每一个文件

9 for x inall_files:10 filename = x.split('/')[-1]11 local_filename =os.path.join(local_dir, filename)12 print u'Get文件%s传输中...' %filename13 sftp.get(x, local_filename)

上面方法将remote_dir目录中的所有文件都get到了本地local_dir目录中,但是在本地没有保持与远端一致的目录结构,只是简单将所有文件保存在local_dir目录中。

如果要保持与远端的目录结构一致,就需要在本地ocal_dir中创建子目录,这里暂且不讲述了,如有这种需求可思考一下。

下面再来看看put,其实与get几乎一样,现在扫描本地目录,然后依次遍历文件并put到远端,

由于是对本地目录做扫描,因此不需要调用SFTP中的文件目录处理接口了,直接使用python的os库即可,代码如下:

1 #------获取本地指定目录及其子目录下的所有文件------

2 def __get_all_files_in_local_dir(self, local_dir):3 #保存所有文件的列表

4 all_files =list()5

6 #获取当前指定目录下的所有目录及文件,包含属性值

7 files =os.listdir(local_dir)8 for x infiles:9 #local_dir目录中每一个文件或目录的完整路径

10 filename =os.path.join(local_dir, x)11 #如果是目录,则递归处理该目录

12 ifos.path.isdir(x):13 all_files.extend(self.__get_all_files_in_local_dir(filename))14 else:15 all_files.append(filename)16 returnall_files17

18 defsftp_put_dir(self, local_dir, remote_dir):19 t = paramiko.Transport(sock=(self.ip, 22))20 t.connect(username=self.username, password=self.password)21 sftp =paramiko.SFTPClient.from_transport(t)22

23 #去掉路径字符穿最后的字符'/',如果有的话

24 if remote_dir[-1] == '/':25 remote_dir = remote_dir[0:-1]26

27 #获取本地指定目录及其子目录下的所有文件

28 all_files = self.__get_all_files_in_local_dir(local_dir)29 #依次put每一个文件

30 for x inall_files:31 filename = os.path.split(x)[-1]32 remote_filename = remote_dir + '/' +filename33 print u'Put文件%s传输中...' %filename34 sftp.put(x, remote_filename)

测试代码如下:

1 if __name__ == '__main__':2 remote_path = r'/home/sea'

3 local_path = r'E:\PythonFiles\Learn\testsftp'

4

5 host = Linux('192.168.180.128', 'root', '1234')6

7 #将远端remote_path目录中的所有文件get到本地local_path目录

8 host.sftp_get_dir(remote_path, local_path)9 ## 将本地local_path目录中的所有文件put到远端remote_path目录

10 #host.sftp_put_dir(remote_path, local_path)

11

12 #运行结果

13 Get文件.profile传输中...14 Get文件.inputrc传输中...15 Get文件.emacs传输中...16 Get文件.bash_history传输中...17 Get文件.bashrc传输中...

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值