Guest User

Untitled

a guest
Apr 2nd, 2019
52
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.57 KB | None | 0 0
  1. import ftplib
  2. import os
  3. import re
  4.  
  5. """
  6. MIT license: 2017 - Jwely
  7.  
  8. Example usage:
  9. ``` python
  10. import ftplib
  11. ftp = ftplib.FTP(mysite, username, password)
  12. download_ftp_tree(ftp, remote_dir, local_dir)
  13. ```
  14.  
  15. The code above will look for a directory called "remote_dir" on the ftp host, and then duplicate the
  16. directory and its entire contents into the "local_dir".
  17.  
  18. *** Note that if wget is an option, I recommend using that instead ***
  19.  
  20. """
  21.  
  22.  
  23. def _is_ftp_dir(ftp_handle, name, guess_by_extension=True):
  24. """ simply determines if an item listed on the ftp server is a valid directory or not """
  25.  
  26. # if the name has a "." in the fourth to last position, its probably a file extension
  27. # this is MUCH faster than trying to set every file to a working directory, and will work 99% of time.
  28. if guess_by_extension is True:
  29. if len(name) >= 4:
  30. if name[-4] == '.':
  31. return False
  32.  
  33. original_cwd = ftp_handle.pwd() # remember the current working directory
  34. try:
  35. ftp_handle.cwd(name) # try to set directory to new name
  36. ftp_handle.cwd(original_cwd) # set it back to what it was
  37. return True
  38.  
  39. except ftplib.error_perm as e:
  40. print(e)
  41. return False
  42.  
  43. except Exception as e:
  44. print(e)
  45. return False
  46.  
  47.  
  48. def _make_parent_dir(fpath):
  49. """ ensures the parent directory of a filepath exists """
  50. dirname = os.path.dirname(fpath)
  51. while not os.path.exists(dirname):
  52. try:
  53. os.makedirs(dirname)
  54. print("created {0}".format(dirname))
  55. except OSError:
  56. _make_parent_dir(dirname)
  57.  
  58.  
  59. def _download_ftp_file(ftp_handle, name, dest, overwrite):
  60. """ downloads a single file from an ftp server """
  61. _make_parent_dir(dest.lstrip("/"))
  62. if not os.path.exists(dest) or overwrite is True:
  63. try:
  64. with open(dest, 'wb') as f:
  65. ftp_handle.retrbinary("RETR {0}".format(name), f.write)
  66. print("downloaded: {0}".format(dest))
  67. except FileNotFoundError:
  68. print("FAILED: {0}".format(dest))
  69. else:
  70. print("already exists: {0}".format(dest))
  71.  
  72.  
  73. def _file_name_match_patern(pattern, name):
  74. """ returns True if filename matches the pattern"""
  75. if pattern is None:
  76. return True
  77. else:
  78. return bool(re.match(pattern, name))
  79.  
  80.  
  81. def _mirror_ftp_dir(ftp_handle, name, overwrite, guess_by_extension, pattern):
  82. """ replicates a directory on an ftp server recursively """
  83. for item in ftp_handle.nlst(name):
  84. if _is_ftp_dir(ftp_handle, item, guess_by_extension):
  85. _mirror_ftp_dir(ftp_handle, item, overwrite, guess_by_extension, pattern)
  86. else:
  87. if _file_name_match_patern(pattern, name):
  88. _download_ftp_file(ftp_handle, item, item, overwrite)
  89. else:
  90. # quietly skip the file
  91. pass
  92.  
  93.  
  94. def download_ftp_tree(ftp_handle, path, destination, pattern=None, overwrite=False, guess_by_extension=True):
  95. """
  96. Downloads an entire directory tree from an ftp server to the local destination
  97. :param ftp_handle: an authenticated ftplib.FTP instance
  98. :param path: the folder on the ftp server to download
  99. :param destination: the local directory to store the copied folder
  100. :param pattern: Python regex pattern, only files that match this pattern will be downloaded.
  101. :param overwrite: set to True to force re-download of all files, even if they appear to exist already
  102. :param guess_by_extension: It takes a while to explicitly check if every item is a directory or a file.
  103. if this flag is set to True, it will assume any file ending with a three character extension ".???" is
  104. a file and not a directory. Set to False if some folders may have a "." in their names -4th position.
  105. """
  106. path = path.lstrip("/")
  107. original_directory = os.getcwd() # remember working directory before function is executed
  108. os.chdir(destination) # change working directory to ftp mirror directory
  109.  
  110. _mirror_ftp_dir(
  111. ftp_handle,
  112. path,
  113. pattern=pattern,
  114. overwrite=overwrite,
  115. guess_by_extension=guess_by_extension)
  116.  
  117. os.chdir(original_directory) # reset working directory to what it was before function exec
  118.  
  119.  
  120. if __name__ == "__main__":
  121. # Example usage mirroring all jpg files in an FTP directory tree.
  122. mysite = "some_ftp_site"
  123. username = "anonymous"
  124. password = None
  125. remote_dir = ""
  126. local_dir = ""
  127. pattern = ".*\.jpg$"
  128. ftp = ftplib.FTP(mysite, username, password)
  129. download_ftp_tree(ftp, remote_dir, local_dir, pattern=pattern, overwrite=False, guess_by_extension=True)
Add Comment
Please, Sign In to add comment