4

I want to connect through FTP to an address and then delete all contents. Currently I am using this code:

from ftplib import FTP
import shutil
import os

ftp = FTP('xxx.xxx.xxx.xxx')
ftp.login("admin", "admin")

for ftpfile in ftp.nlst():
    if os.path.isdir(ftpfile)== True:
        shutil.rmtree(ftpfile)
    else:
        os.remove(ftpfile)

My problem is I always get this error when he is trying to delete the first file:

    os.remove(ftpfile)
WindowsError: [Error 2] The system cannot find the file specified: somefile.sys

Anyone has an idea why?

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
Adrian
  • 19,440
  • 34
  • 112
  • 219

6 Answers6

6
for something in ftp.nlst():
    try:
        ftp.delete(something)
    except Exception:
        ftp.rmd(something)

Any other ways?

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
pravin
  • 501
  • 2
  • 7
5

This function deletes any given path recursively:

# python 3.6    
from ftplib import FTP

def remove_ftp_dir(ftp, path):
    for (name, properties) in ftp.mlsd(path=path):
        if name in ['.', '..']:
            continue
        elif properties['type'] == 'file':
            ftp.delete(f"{path}/{name}")
        elif properties['type'] == 'dir':
            remove_ftp_dir(ftp, f"{path}/{name}")
    ftp.rmd(path)

ftp = FTP(HOST, USER, PASS)
remove_ftp_dir(ftp, 'path_to_remove')
Dmytro Gierman
  • 335
  • 3
  • 8
2
from ftplib import FTP
import shutil
import os

ftp = FTP("hostname")

ftp.login("username", "password")


def deletedir(dirname):

    ftp.cwd(dirname)

    print(dirname)

    for file in ftp.nlst():

        try:
            ftp.delete(file)

        except Exception:
            deletedir(file)

    ftp.cwd("..")
    ftp.rmd(dirname)
            

for ftpfile in ftp.nlst():

    try:

        ftp.delete(ftpfile)

    except Exception:

        deletedir(ftpfile)
Flavia Giammarino
  • 7,987
  • 11
  • 30
  • 40
vivek
  • 21
  • 1
  • Please don't post only code as an answer, but also provide an explanation what your code does and how it solves the problem of the question. Answers with an explanation are usually more helpful and of better quality, and are more likely to attract upvotes. – Tyler2P Oct 17 '21 at 08:18
0
ftp.nlst()

The above statement returns a list of file names.

os.remove()

The above statement requires a file path.

pravin
  • 501
  • 2
  • 7
  • Yes, and I am iterating the list and trying to delete the file, I don't think I need a path here – Adrian Apr 06 '12 at 12:38
  • 2
    But doesn't os.remove() remove locally and not remotely corresponding to what ftp.nlst() returned? What am I missing? – octopusgrabbus Apr 06 '12 at 13:43
  • http://docs.python.org/library/os.html says that the argument for os.remove() is path and and not mere file name. – pravin Apr 06 '12 at 13:43
  • @octopusgrabbus you are correct. i think it might be possible to check file/directory using ftp.retrlines('MSDL') and then form ftp paths accordingly. any other ways? – pravin Apr 06 '12 at 13:47
  • It's in the ftp documentation for Python's ftp, and I don't have my samples. – octopusgrabbus Apr 06 '12 at 13:49
  • http://stackoverflow.com/questions/3406734/how-to-delete-all-files-in-directory-on-remote-server-in-python So I guess its posiblle to delte filed remotely – Adrian Apr 06 '12 at 14:12
0
from ftplib import FTP
#--------------------------------------------------
class FTPCommunicator():

    def __init__(self):

        self.ftp = FTP()
        self.ftp.connect('server', port=21, timeout=30)
        self.ftp.login(user="user", passwd="password")

    def getDirListing(self, dirName):

        listing = self.ftp.nlst(dirName)

        # If listed a file, return.
        if len(listing) == 1 and listing[0] == dirName:
            return []

        subListing = []
        for entry in listing:
            subListing += self.getDirListing(entry)

        listing += subListing

        return listing

    def removeDir(self, dirName):

        listing = self.getDirListing(dirName)

        # Longest path first for deletion of sub directories first.
        listing.sort(key=lambda k: len(k), reverse=True)

        # Delete files first.
        for entry in listing:
            try:
                self.ftp.delete(entry)
            except:
                pass

        # Delete empty directories.
        for entry in listing:
            try:
                self.ftp.rmd(entry)
            except:
                pass

        self.ftp.rmd(dirName)

    def quit(self):

        self.ftp.quit()
#--------------------------------------------------
def main():

    ftp = FTPCommunicator()
    ftp.removeDir("/Untitled")
    ftp.quit()
#--------------------------------------------------
if __name__ == "__main__":
    main()
#--------------------------------------------------
nvd
  • 2,995
  • 28
  • 16
0

@Dmytro Gierman has the best option in my opinion, however, I don't want to delete the main folder, only the subfolder and all files inside. Here is a script in order to make it work

import ftplib
# python 3.9
def remove_ftp_dir(ftp, path, mainpath):
for (name, properties) in ftp.mlsd(path=path):
    if name in ['.', '..']:
        continue
    elif properties['type'] == 'file':
        ftp.delete(f"{path}/{name}")
    elif properties['type'] == 'dir':
        remove_ftp_dir(ftp, f"{path}/{name}", mainpath)
if path != mainpath: #only deletes subdirectories not he mainpath
    ftp.rmd(path)
  • Imo better solution is to move the `ftp.rmd(path)` call after the `remove_ftp_dir` (into the `elif properties['type'] == 'dir':` branch). That way its executed for subfolders, but not for the top-level folder. – Martin Prikryl May 20 '22 at 06:17