Welcome, guest | Sign In | My Account | Store | Cart

This script filled the need to have a scheduled directory synch occur via FTP. I also realized I could use it to clean out a directory without much effort. There are probably more robust examples out there, but this one should be easily modifiable for FTP newbies. It uses Sets to speed up finding missing files from the local directory.

Python, 65 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
def moveFTPFiles(serverName,userName,passWord,remotePath,localPath,deleteRemoteFiles=False,onlyDiff=False):
	"""Connect to an FTP server and bring down files to a local directory"""
	import os
	from sets import Set
	from ftplib import FTP
	try:
		ftp = FTP(serverName)
	except:
		print "Couldn't find server"
	ftp.login(userName,passWord)
	ftp.cwd(remotePath)
	
	try:
		print "Connecting..."
		if onlyDiff:
			lFileSet = Set(os.listdir(localPath))
			rFileSet = Set(ftp.nlst())
			transferList = list(rFileSet - lFileSet)
			print "Missing: " + str(len(transferList))
		else:
			transferList = ftp.nlst()
		delMsg = ""	
		filesMoved = 0
		for fl in transferList:
			# create a full local filepath
			localFile = localPath + fl
			grabFile = True
			if grabFile:				
				#open a the local file
				fileObj = open(localFile, 'wb')
				# Download the file a chunk at a time using RETR
				ftp.retrbinary('RETR ' + fl, fileObj.write)
				# Close the file
				fileObj.close()
				filesMoved += 1
				
			# Delete the remote file if requested
			if deleteRemoteFiles:
				ftp.delete(fl)
				delMsg = " and Deleted"
			
		print "Files Moved" + delMsg + ": " + str(filesMoved) + " on " + timeStamp()
	except:
		print "Connection Error - " + timeStamp()
	ftp.close() # Close FTP connection
	ftp = None

def timeStamp():
    """returns a formatted current time/date"""
    import time
    return str(time.strftime("%a %d %b %Y %I:%M:%S %p"))

if __name__ == '__main__':
	#--- constant connection values
	ftpServerName = "ftpservername.com"
	ftpU = "ftpusername"
	ftpP = "ftppassword"
	remoteDirectoryPath = "remote/ftp/subdirectory"
	localDirectoryPath = """local\sub\directory"""
	
	print "\n-- Retreiving Files----\n"
	
	deleteAfterCopy = False 	#set to true if you want to clean out the remote directory
	onlyNewFiles = True			#set to true to grab & overwrite all files locally
	moveFTPFiles(ftpServerName,ftpU,ftpP,remoteDirectoryPath,localDirectoryPath,deleteAfterCopy,onlyNewFiles)

This could stand to have a more robust synch method - just grabbing the files that don't exist locally doesn't help you with newer/changed files of the same name.

I'm also using a try/except block that covers a little too much code. More granular error handling would be nice, but might make it's readability drop.

6 comments

Guy Argo 16 years, 5 months ago  # | flag

huh? Where's the definition of ZzWw?

EyePulp (author) 16 years ago  # | flag

Rats. Sorry about that - it appears my pop-up blocking/ad munching software killed that line when I submitted (and tried to re-edit) the code.

The line has been changed to "open"

se5a se5a 15 years, 3 months ago  # | flag

stumped. I can't get this working

this is what I get:

-- Retreiving Files----

Couldn't find server Traceback (most recent call last):

File "C:\Python24\projects\zipstuff\ftp.py", line 66, in ?

moveFTPFiles(ftpServerName,ftpU,ftpP,remoteDirectoryPath,localDirectoryPath,

deleteAfterCopy,onlyNewFiles)

File "C:\Python24\projects\zipstuff\ftp.py", line 10, in moveFTPFiles

ftp.login(userName,passWord)

UnboundLocalError: local variable 'ftp' referenced before assignment

The ftpservername is correct, as is the ftpU and ftpP.

What could I be doing wrong?

se5a se5a 15 years, 2 months ago  # | flag

got it. ah I see, you don't include the ftp:// in the address, just the address without the ftp:// duh

Brendan owens 8 years, 3 months ago  # | flag

Thanks very much for sharing. A lot of this is beyond me at present as I just started python yesterday. I was hoping to understand why I'm getting a syntax error by looking at your code. Alas, it is far to advanced with many function calls. If you have a moment can you tell me why I can't change to a specific folder on the ftp site without getting an error message. I can upload a file directly to the root but can't get pass an error when i try to change the directory. - thanks.

(keep getting this error message: TypeError: cwd() missing 1 required positional argument: 'dirname' I have tried many variations for the directory argument; 'mychosenfolder' - '/mychosenfolder/' '//mychosenfolder//' and even assigned the string to a variable and used that in the FTP.cwd statmente (as in the code below) But still get the same error message. And YES, the folder does exist and it is writeable to.

Code below

# ftpfileupload.py
# uploads a named file to a specific directory on a website

import ftplib
from ftplib import FTP 
print('Conecting to FTP server . . . Please wait . . ')
session = FTP('www.somewebsite.com','username','password')
file = open('sample.txt','rb')                  # file to send
# print(FTP.pwd()) # Get the current path - this does work either
myfolder = '/mychosenfolder/'
FTP.cwd(myfolder)                              # Change Directory
print('Uploading File Now . . . Please wait . . ')
session.storbinary('STOR sample.txt', file)     # send the file
print('File Uploaded')
file.close()                                    # close file and FTP
session.quit()
Cesae 4 years, 7 months ago  # | flag

Hello

I have issue with images named with a dash characters.... how can i still use this script and make it working?? (original file name is DJ3200-03-BX.jpg cmd 'RETR DJ3200?03?BX.jpg' resp '550 The filename, directory name, or volume label syntax is incorrect. ' Connection Error - Sun 30 Apr 2017 10:29:13 AM