Reputation: 1055
I am trying to copy all directories with files and subdirectories from an FTP server to a local directory. The goal is to create a copy of all of them at the first execution of the program and update the changed ones at the other executions or add the newly added.
My FTP directory structure is:
├── _directory1
│ ├──_subdirectory1
│ ├── file1.py
│ ├── file2.py
│ ├──_subdirectory2
│ ├── file3.py
│ ├── file4.py│
| ├──_subdirectory3
│ ├── file3.py
│ ├── file4.py
│ └── packages.py
│ └── somefile.py
│ └── somepdf.pdf
├── _directory2
│ ├──_subdirectory2.1
│ ├── file2.1.py
Here is my code:
import os
import os.path
from ftplib import FTP, error_perm
from io import BytesIO
host = 'localhost'
username = 'user'
password = 'password'
port = 21
ftp = FTP()
ftp.connect(host, port)
ftp.login(username, password)
filenameCV = "C:/Users/User/Desktop/test"
# ftp.set_debuglevel(2)
def copy_all_files(ftp_server, path):
for filename in ftp_server.nlst():
print(filename)
try:
ftp_server.size(filename)
if os.path.exists(os.path.join(path, filename)):
with open(os.path.join(path, filename), "rb") as file:
r = BytesIO()
try:
ftp_server.retrbinary('RETR ' + filename, r.write)
if BytesIO(file.read()).getvalue() != r.getvalue():
print(filename+"has changed")
ftp_server.retrbinary('RETR ' + filename,
open(os.path.join(path, filename),
'wb').write)
except Exception as ee:
print(ee)
else:
ftp_server.retrbinary('RETR ' + filename, open(os.path.join(path, filename), 'wb').write)
except:
try:
if not os.path.exists(os.path.join(path, filename)):
os.mkdir(os.path.join(path, filename))
ftp_server.cwd(filename)
copy_all_files(ftp_server, os.path.join(path, filename))
except:
pass
copy_all_files(ftp, filenameCV)
ftp.quit()
The problem is that my code creates directory 1 and directory 2 from the FTP, but copies and changes only subdirectory1 and files inside it, the rest of the directories are empty, the files from directory1 level are missing, subdirectories 2,3 and directory 2 are empty and also the pdf from the directory level is copied as a dir. Do I need to change ftp.cwd or what is the reason for not being copied the other dirs?
Upvotes: 1
Views: 240
Reputation: 202168
You enter the remote folders here:
ftp_server.cwd(filename)
But you never leave them.
Either:
Leave the folder, once you download its contents:
ftp_server.cwd(filename)
copy_all_files(ftp_server, os.path.join(path, filename))
ftp_server.cwd("..")
Or use absolute paths when entering the folders. That way the cwd
will work, no matter there you are at that particular moment. Like here:
Downloading a directory tree with ftplib
In a broad sense, your question is actually a duplicate of the above one – Why are you trying to implement something, for which there's already a working solution?
Upvotes: 1