I'm trying to download several folders from an ftp server with Python 3 using ftplib.
I have a list of the names of the folders. They are all located in a folder 'root'. The problem is that I don't know how to navigate through them. When I use cwdI can go to a deeper directory, but how do I get up again?
I'm trying to get something like
list = ["folder1", "folder2", "folder3"]
for folder in list:
##navigate to folder
##do something
You can retrieve current directory using FTP.pwd method. Remember that directory before change directory.
parent_dir = ftp_object.pwd()
list = ["folder1", "folder2", "folder3"]
for folder in list:
ftp_object.cwd('{}/{}'.format(parent_dir, folder))
ftp_object.cwd(parent_dir) # go to parent directory
I made some changes to code I found here
You have to make the destination folder before running the code.
Also, the site I used did not require username or pass.
Please let me know if this works. I am wondering if I should "put this in my back pocket" and save it to my external hard drive.
#!/usr/bin/python
import sys
import ftplib
import urllib.request
import os
import time
import errno
server = "ftp.analog.com"
#user = ""
#password = ""
source = "/pub/MicroConverter/ADuCM36x/"
destination0 = "C:/NewFolder/" # YOU HAVE TO UT THIS NEW FOLDER IN C: BEFORE RUNNING
interval = 0.05
ftp = ftplib.FTP(server)
ftp.login()#(user, password)
count = 0 #We need this variable to make the first folder correctly
def downloadFiles(path, destination):
try:
ftp.cwd(path)
os.chdir(destination)
mkdir_p(destination[0:len(destination)-1] + path)
print ("Created: " + destination[0:len(destination)-1] + path )
except OSError:
pass
except ftplib.error_perm:
print ( "Error: could not change to " + path )
sys.exit("Ending Application")
filelist=ftp.nlst()
print(filelist)
for file in filelist:
time.sleep(interval)
if "." in file :
url = ("ftp://" + server + path + file)
urllib.request.urlretrieve(url, destination + path + file)
else:
try:
ftp.cwd(path + file + "/")
downloadFiles(path + file + "/", destination)
except ftplib.error_perm:
os.chdir(destination[0:len(destination)-1] + path)
try:
ftp.retrbinary("RETR " + file, open(os.path.join(destination + path, file),"wb").write)
print ("Downloaded: " + file)
except:
print ("Error: File could not be downloaded " + file)
return
def mkdir_p(path):
try:
os.makedirs(path)
except OSError as exc:
if exc.errno == errno.EEXIST and os.path.isdir(path):
pass
else:
raise
downloadFiles(source, destination0)
#ftp.quit()
Related
Im creating a folder with PDF Files in it. Im using PyPDF2 in Django. It works all fine, the folder with the files in it is created. But after that, i cant delete it without stopping the running server. It throws an error saying the file is used by another application.
Do anyone know how i can fix that problem?
Here is the code snippet, which creates the folder with the pdf files in it:
# Merge Befunde
for folder in os.listdir(os.getcwd()):
mergeFile = PyPDF2.PdfFileMerger()
for filename in os.listdir(os.getcwd() + "\\" + folder):
if filename.endswith(".pdf"):
file = os.getcwd() + "\\" + folder + "\\" + filename
try:
mergeFile.append(PyPDF2.PdfFileReader(file))
except:
print("Error in", file)
else:
continue
mergeFile.write(folder + ".pdf")
mergeFile.close()
I found out that maybe the problem is not with the files im creating with the PyPDF2 Library.
First im reating a folder with the os module. After that i copy and create some PDF files in it. After finishing i want to rename or move the folder, but it throws an error that this file is being used by another user.
But i can delete or rename the files i have created in the folder. After i stop the django server the problem does not occur and i can do anything i want.
try:
os.mkdir(folder_name)
except OSError as error:
pass
shutil.copy(path, dest)
newname = f"{x['parent_id']}_{x['prob_nr']}_{parameter}.pdf"
os.rename(dest + "\\" + datei, dest+ "\\" + newname)
# Merge Befunde
for folder in os.listdir(os.getcwd()):
mergeFile = PyPDF2.PdfMerger()
for filename in os.listdir(os.getcwd() + "\\" + folder):
if filename.endswith(".pdf"):
file = os.getcwd() + "\\" + folder + "\\" + filename
try:
mergeFile.append(file)
except:
print("Error in", file)
else:
continue
mergeFile.write(folder + ".pdf")
mergeFile.close()
I need to copy a file to a subdirectory with its name changed to name_timestamp(by appending the time stamp).
I'm using a COPY method on a csv file and once that copy is done, I need to move the CSV file to a subdirectory and rename it to CSV_timestamp.
Below is the sample code. Can anyone help me or suggest me on how to do this?
import os, shutil, time
if not os.path.exists(dirName):
os.mkdir(dirName)
print("Directory " , dirName , " Created ")
else:
print("Directory " , dirName , " already exists")
def copyFile(src, dest):
try:
shutil.copy(src, dest)
# eg. src and dest are the same file
except shutil.Error as e:
print('Error: %s' % e)
# eg. source or destination doesn't exist
except IOError as e:
print('Error: %s' % e.strerror)
os.rename("path/to/current/age.csv", "path/to/new/destination/for/age.csv")
shutil.move("path/to/current/age.csv", "path/to/new/destination/for/age.csv")
Sticking to your approach (with a function that checks whether the directory exists etc.), you could do the following:
import os
import shutil
from time import gmtime, strftime
def copyFile(old_path, new_directory):
# check if the directory already exists
if not os.path.exists(new_directory):
os.mkdir(new_directory)
print(f"Directory {new_directory} Created.")
else:
print(f"Directory {new_directory} already exists.")
# create new path from new_directory, the filename and the timestamp
new_path = new_directory + old_path.split("/")[len(old_path)-1].split(".")[0] + strftime("%Y_%m_%d", gmtime()) + ".csv"
# copy the file to the new path
try:
shutil.copy(old_path, new_path)
# eg. src and dest are the same file
except shutil.Error as e:
print(f"Error: {e}")
# eg. source or destination doesn't exist
except IOError as e:
print(f"Error: {e.strerror}")
old_path = '/path/to/directory/file.csv'
new_directory = '/path/to/new/directory/'
copyFile(old_path, new_directory)
Please note that
As of Python 3.6, you can use f-strings to include variables in strings more easily.
It wasn't clear to me what kind of timestamp you are looking for.
This approach will give you a stamp in the format of YYYY_MM_DD
of the current day, but you could easily change that, see the
documentation on the time package.
After using shutil.copy, you don't need shutil.move any more, as
the first already copied your file and saved it to the destination
path.
It should be as simple as setting your destination path to whatever directory you want it in when you finish.
For example, say your file is in users/foo/bar/myfile.csv (this would be your src path). Suppose you want that file's copy in users/mydocuments/bar/foo/mynewfile.csv (this would be your dest path).
All you'd need to do is:
import shutil
import os
src = 'users/foo/bar/myfile.csv'
tstamp = os.path.getmtime(path)
dest = 'users/mydocuments/bar/foo/mynewfile' + tstamp + '.csv'
shutil.move(src,dest)
you can use os.rename() insteed
import time
timestamp_name=int(time.time())
os.rename('path/to/file/name.text','path/to/file/'+timestamp_name+'.txt)
I setup the Dropbox uploader script for the Raspberry pi and was able to successfully upload a file to Dropbox, but now I need to setup an auto script to upload the files into a specific destination folder within Dropbox. I recently found a script that would do just that, but my problem with it is that I cant specify a Destination folder within Dropbox. Other users replied on the forum post asking for an input for a destination folder as well but the post has been inactive for months.
https://github.com/andreafabrizi/Dropbox-Uploader
https://www.raspberrypi.org/forums/viewtopic.php?t=164166
I researched other stackoverflow posts related to this problem, but they would not work in my circumstance. Both scripts work great but I would like to see if its possible to alter the script to specify a destination folder within dropbox.
syncdir is the local folder for upload.
I need an input for something like "/dropbox/TeamFolder" instead of just uploading the files straight into my Dropbox user directory.
import os
import subprocess
from subprocess import Popen, PIPE
#The directory to sync
syncdir="/home/pi/Dropbox-Files/"
#Path to the Dropbox-uploaded shell script
uploader = "/home/pi/Dropbox-Uploader/dropbox_uploader.sh"
#If 1 then files will be uploaded. Set to 0 for testing
upload = 1
#If 1 then don't check to see if the file already exists just upload it, if 0 don't upload if already exists
overwrite = 0
#If 1 then crawl sub directories for files to upload
recursive = 1
#Delete local file on successfull upload
deleteLocal = 0
#Prints indented output
def print_output(msg, level):
print((" " * level * 2) + msg)
#Gets a list of files in a dropbox directory
def list_files(path):
p = Popen([uploader, "list", path], stdin=PIPE, stdout=PIPE, stderr=PIPE)
output = p.communicate()[0].decode("utf-8")
fileList = list()
lines = output.splitlines()
for line in lines:
if line.startswith(" [F]"):
line = line[5:]
line = line[line.index(' ')+1:]
fileList.append(line)
return fileList
#Uploads a single file
def upload_file(localPath, remotePath):
p = Popen([uploader, "upload", localPath, remotePath], stdin=PIPE, stdout=PIPE, stderr=PIPE)
output = p.communicate()[0].decode("utf-8").strip()
if output.startswith("> Uploading") and output.endswith("DONE"):
return 1
else:
return 0
#Uploads files in a directory
def upload_files(path, level):
fullpath = os.path.join(syncdir,path)
print_output("Syncing " + fullpath,level)
if not os.path.exists(fullpath):
print_output("Path not found: " + path, level)
else:
#Get a list of file/dir in the path
filesAndDirs = os.listdir(fullpath)
#Group files and directories
files = list()
dirs = list()
for file in filesAndDirs:
filepath = os.path.join(fullpath,file)
if os.path.isfile(filepath):
files.append(file)
if os.path.isdir(filepath):
dirs.append(file)
print_output(str(len(files)) + " Files, " + str(len(dirs)) + " Directories",level)
#If the path contains files and we don't want to override get a list of files in dropbox
if len(files) > 0 and overwrite == 0:
dfiles = list_files(path)
#Loop through the files to check to upload
for f in files:
print_output("Found File: " + f,level)
if upload == 1 and (overwrite == 1 or not f in dfiles):
fullFilePath = os.path.join(fullpath,f)
relativeFilePath = os.path.join(path,f)
print_output("Uploading File: " + f,level+1)
if upload_file(fullFilePath, relativeFilePath) == 1:
print_output("Uploaded File: " + f,level + 1)
if deleteLocal == 1:
print_output("Deleting File: " + f,level + 1)
os.remove(fullFilePath)
else:
print_output("Error Uploading File: " + f,level + 1)
#If recursive loop through the directories
if recursive == 1:
for d in dirs:
print_output("Found Directory: " + d, level)
relativePath = os.path.join(path,d)
upload_files(relativePath, level + 1)
#Start
upload_files("",1)
When you use the dropbox_uploader.sh script you specify the folder to save the file to on the Dropbox account. However, that is limited to whatever settings you gave the "app" in the Dropbox settings to get your access token. You can set it to allow reading/writing anyplace in your Dropbox account or only in a specific folder.
Look for "Permission Type" and "App Folder Name" on the Dropbox apps setup page: https://www.dropbox.com/developers/apps
I wanted to supply python with a windows 'data path' that could be used to set up input processing. I googled this with no luck, and now figure I am on my own.
There appears to be many ways of reading in a file with python, and after some frustration with "\" and "/" and windows path names I found a way to get my data path set up. It is not a general approach but should serve me well.
Related Questions: Is this code ugly? Is this a nonstandard method? Are there elegant features in 3.6 that should be used?
### Title: Process an input file using a 'data path' for a user on windows
import sys
import os
print("OK, starting program...")
file_processed = False
for path, dirs, files in os.walk("/Users/Mike"):
if file_processed: break
for file in files:
if file_processed: break
if file == 'seriousdata.txt':
my_path = os.path.abspath(path)
my_dsn = os.path.join(my_path, file)
print("Opening txt file " + my_dsn + " for input.")
with open(my_dsn) as da_lines:
textlines = (line.rstrip('\r\n') for line in da_lines)
for line in textlines:
print(line)
file_processed = True
if file_processed:
pass
else:
print("File not found")
print("OK, program execution has ended.")
sys.exit() # END SAMPLE CODE SNIPPET
From looking at your code, I'm assuming that you want to start at one directory, and move through each child directory, printing out the matching filename's contents if it is found.
If so, then this is way to do this with recursion:
import os
def recursive_list(path, filename):
files = os.listdir(path)
for name in files:
try:
p = os.path.join(path, name)
if os.path.isdir(p):
recursive_list(p, filename)
else:
if name == filename:
with open(p, "r") as f:
print(f.read())
except PermissionError:
pass
return
recursive_list("/home/jebby/Desktop","some_file.txt")
This will start out listing files in path. For every file that is found, if that file is a directory, then the function itself is called (Starting at the path to that folder). If filename matches the name of any file in the current directory, it will be printed (if the user has permissions for that file).
Otherwise, if you only want to read the filename from a known directory without walking down the directory tree:
import os
data_path = "/home/jebby/Desktop"
file_you_want = "filename.txt"
with open(os.path.join(data_path, file_you_want), "r") as f:
content = f.read()
print(content)
The main question would be : Do you know the location of the file?
Jebby has an answer to crawl through the directories.
Here is a solution without using "import os"
dir_fullpath = "c:/project_folder/data"
dir_path = "data"
filename = "file.txt"
try:
f = open(dir_path + "/" + filename, 'r')
# print("open " +dir_path + "\" + filename)
# data=[]
for line in f:
print (line.rstrip())
# data.append(line.rstrip())
f.close()
except IOError:
print("Fail to open" + dir_path + "\" + filename)
I need to upload some files into different directories on ftp server. The files are named like this:
Broad_20140304.zip.
External_20140304.zip.
Report_20140304.
They must be placed into the next directories:
Broad.
External.
Report.
I want something like: for filename like External put it into External directory.
I have the next code, but this put all zip files into the "Broad" Directory. I want just the broad.zip file into this directory, not all of them.
def upload_file():
route = '/root/hb/zip'
files=os.listdir(route)
targetList1 = [fileName for fileName in files if fnmatch.fnmatch(fileName,'*.zip')]
print 'zip files on target list:' , targetList1
try:
s = ftplib.FTP(ftp_server, ftp_user, ftp_pass)
s.cwd('One/Two/Broad')
try:
print "Uploading zip files"
for record in targetList1:
file_name= ruta +'/'+ record
print 'uploading file: ' + record
f = open(file_name, 'rb')
s.storbinary('STOR ' + record, f)
f.close()
s.quit()
except:
print "file not here " + record
except:
print "unable to connect ftp server"
The function has hard coded value for s.cwd so it is putting all files in one dir. You can try something like below to get the remote directory dynamically from file name.
Example: (Not Tested)
def upload_file():
route = '/root/hb/zip'
files=os.listdir(route)
targetList1 = [fileName for fileName in files if fnmatch.fnmatch(fileName,'*.zip')]
print 'zip files on target list:' , targetList1
try:
s = ftplib.FTP(ftp_server, ftp_user, ftp_pass)
#s.cwd('One/Two/Broad') ##Commented Hard-Coded
try:
print "Uploading zip files"
for record in targetList1:
file_name= ruta +'/'+ record
rdir = record.split('_')[0] ##get the remote dir from filename
s.cwd('One/Two/' + rdir) ##point cwd to the rdir in last step
print 'uploading file: ' + record
f = open(file_name, 'rb')
s.storbinary('STOR ' + record, f)
f.close()
s.quit()
except:
print "file not here " + record
except:
print "unable to connect ftp server"