Small simple Python FTP file delete script
New here? Learn about Bountify and follow @bountify to get notified of new bounties! x

I need a small Python script which will:

  1. Accept FTP server login and FTP address and path parameters
  2. Delete all files and folders recursively in target FTP server/path
FYI: Will be done in the newest Python.
optimist 5 months ago
Hey, the host server is Ubuntu 14.04 and with Python 3. The target server I'm not sure
user856 5 months ago
awarded to optimist
Tags
python

Crowdsource coding tasks.

5 Solutions


Hello

this script should do the work

from ftplib import FTP
def recurse(ftp):
    print ftp.pwd()
    for d in ftp.nlst():
        try:
            ftp.cwd(d)
            cleanOut(ftp)
            ftp.cwd('..')
            ftp.rmd(d)
        except:
            pass
        else:
            try:
                ftp.cwd(d)
                recurse(ftp)
                ftp.cwd('..')
            except:
                pass # not a directory; ignore

def cleanOut(ftp):
    print 'cleanout ',ftp.pwd()
    for d in ftp.nlst():
        try:
            ftp.delete(d) # delete the file
        except:
            ftp.cwd(d) # it's actually a directory; clean it
            cleanOut(ftp)
            ftp.cwd('..')
            ftp.rmd(d)

ftp = FTP('123.123.123.123')
ftp.login('USERNAME','PASSWORD')
ftp.cwd("directory_to_clean")
recurse(ftp)

ftp.quit()
Winning solution

I created a test ftp server to check the script. It works.

Usage

This will recursively delete directory bb, aa will be undeleted.
(Note, my hosting showed directory /home/www/aa/bb but I needed to pass it as aa/bb)

ftp-rm-tree.py -s optimist856.yourfreehosting.net -u optimist856 -w password1 -p "aa/bb"

ftp-rm-tree.py

#!/usr/bin/python

import sys, os, getopt, ftplib

def FtpRmTree(ftp, path):
    wd = ftp.pwd()

    try:
        names = ftp.nlst(path)
    except ftplib.all_errors as e:
        # some FTP servers complain when you try and list non-existent paths
        print('FtpRmTree: Could not remove {0}: {1}'.format(path, e))
        return

    for name in names:
        if os.path.split(name)[1] in ('.', '..'): continue

        print('FtpRmTree: Checking {0}'.format(name))

        try:
            ftp.cwd(name)  # if we can cwd to it, it's a folder
            ftp.cwd(wd)  # don't try a nuke a folder we're in
            FtpRmTree(ftp, name)
        except ftplib.all_errors:
            ftp.delete(name)

    try:
        ftp.rmd(path)
    except ftplib.all_errors as e:
        print('FtpRmTree: Could not remove {0}: {1}'.format(path, e))

def main(argv):
   host = ''
   user = ''
   psw = ''
   path = ''
   usage = 'Usage: ftp-rm-tree.py -s <host> -u <user> -w <psw> -p <path>'
   try:
      opts, args = getopt.getopt(argv,"hs:u:w:p:",["help","host=","user=","pass=","path="])
   except getopt.GetoptError:
      print(usage)
      sys.exit(2)
   for opt, arg in opts:
      if opt in ("-i", "--help"):
         print(usage)
         sys.exit()
      elif opt in ("-s", "--host"):
         host = arg
      elif opt in ("-u", "--user"):
         user = arg
      elif opt in ("-w", "--pass"):
         psw = arg
      elif opt in ("-p", "--path"):
         path = arg
   print('Will attempt to recursively delete remote path "{}" in "{}"'.format(path, host))
   ftp = ftplib.FTP(host, user, psw)
   FtpRmTree(ftp, path)

if __name__ == "__main__":
   main(sys.argv[1:])
Okay I tested the script and it removes the files but I will have up to thousands of files and currently the script seems to delete sequentially. Is it possible to add a concurrency feature to concurrently delete files? I can send you a tip if necessary :)
user856 5 months ago
The main bottleneck in this code are the ftp calls and it does not matter whether they are made from one thread or another (the connection is the same). This second reason is that this ain't a computationally expensive task on your local processor where parallel execution is useful (more info on this http://softwareengineering.stackexchange.com/questions/238729/can-recursion-be-done-in-parallel-would-that-make-sense). However, don't believe me and it yourself - create two folders with thousands of files. 1) Delete one with the script and then delete other with the script. 2) Run 2 scripts in parallel for different folders. Compare the times for both. TL;DR Yes, I can. But it is not likely to help you:/
optimist 5 months ago
This is as fast as you can get, already.
optimist 5 months ago

       import argparse
    from ftplib import FTP

    parser = argparse.ArgumentParser(description='Delete files via FTP.')
    parser.add_argument('-l', '--login', required = True, help='FTP login')
    parser.add_argument('-p', '--passwd', required = True, help='FTP password')
    parser.add_argument('-u', '--url', required  = True, help='FTP URL')
    parser.add_argument('-d', '--delete', required = True, help='Delete path')
    args = parser.parse_args()

    ftp = FTP(host=args.url,user=args.login,passwd=args.passwd)

    def delete(path):
        ftp.cwd(path)
        files = ftp.nlst()
        d = ftp.pwd()

        if files == None or len(files) == 0:
        ftp.cwd('../')
        ftp.rmd(d)
        if d == args.delete:
            return
        else:
        for f in reversed(files):
            try:
                ftp.delete(f)
                files.remove(f)
                print("%s deleted" % f)
                delete(d)
            except:
                print("%s is directory" % f)
                delete(f)


    delete(args.delete)

I don't know why you would want to use Python for a simple task like this. Just mount it with FUSE and interact with it like a normal filesystem.

curlftpfs ftp.yourserver.com /mnt/ftp/ -o user=username:password
rm -R /mnt/ftp

I have come up with a simple solution for both python2 and python 3, it should be small to your requirements, reusable, simple, and with clear, real-time output messages on the operations being performed just like the terminal...

Below is the script, just copy and paste in a file called delete_all_files_python.py and run this only changing the parameters on the ftp credentials.

from ftplib import FTP

def deleteAllFiles(ftp):
    for n in ftp.nlst():
        try:
            if n not in ('.','..'):
                print 'Working on..'+n
                try:
                    ftp.delete(n)
                    print 'Deleted...'+n
                except Exception:
                    print n+' Not deleted, we suspect its a directory, changing to '+n
                    ftp.cwd(n)
                    deleteAllFiles(ftp)
                    ftp.cwd('..')
                    print 'Trying to remove directory ..'+n
                    ftp.rmd(n)
                    print 'Directory, '+n+' Removed'
        except Exception:
             print 'Trying to remove directory ..'+n
             ftp.rmd(n)
             print 'Directory, '+n+' Removed'

ftp = FTP('your_ftp_host.com')
username='your_ftp_username'
pwd='your_ftp_password'
ftp.login(username, pwd)
ftp.cwd('the_directory_to_remove_all_contents') 
deleteAllFiles(ftp)
print 'Done deleting all Files and Directories!'`

And below is the same implementation of the abovescript but now in python3, this is the script delete_all_files_python3.py

from ftplib import FTP

def deleteAllFiles(ftp):
    for n in ftp.nlst():
        try:
            if n not in ('.','..'):
                print('Working on..'+n)
                try:
                    ftp.delete(n)
                    print('Deleted...'+n)
                except Exception:
                    print(n+' Not deleted, we suspect its a directory, changing to '+n)
                    ftp.cwd(n)
                    deleteAllFiles(ftp)
                    ftp.cwd('..')
                    print('Trying to remove directory ..'+n)
                    ftp.rmd(n)
                    print('Directory, '+n+' Removed')
        except Exception:
            print( 'Trying to remove directory ..'+n)
            ftp.rmd(n)
            print('Directory, '+n+' Removed')

ftp = FTP('your_ftp_host.com')
username="your_ftp_username"
pwd="your_ftp_password"
ftp.login(username, pwd)
ftp.cwd('the_directory_to_remove_all_contents') 
deleteAllFiles(ftp)
print('Done deleting all Files and Directories')
View Timeline