Is it possible to Remove Directory with some contents using pysftp module?
Question:
I am creating a backup script using pysftp module. I am able to upload
and download files. When i am trying to Delete a directory with some
contents i got an exception.
This is what i tried
con = pysftp.Connection('192.168.0.40',username='root',password='clado123')
con.chdir('/root/backup')
con.pwd
con.listdir()
['data', 'test']
data - directory is not empty.
test - directory is empty.
con.rmdir('test')
con.listdir()
['data']
con.rmdir('data')
OSError: Failure
Can any one suggest me a way to solve this problem?
Answers:
rmdir(remotepath)
found at the documenation http://pysftp.readthedocs.io/en/release_0.2.8/pysftp.html#pysftp.Connection.rmdir
I have find out a way. There is method called ‘execute’ in the pysftp connection object. We can execute commands on remote server using this method.
con.execute('rm -rf /root/backup/data')
con.listdir()
[]
remove
all the files from directory and then use rmdir
to remove empty directory. Works for me.
def clean_dir(sftp, dir, files):
assert sftp.isdir(str(dir)), "Outbox does not exist!"
assert files.is_dir(), "Source directory does not exist!"
for capsule in list(files.iterdir()):
target = dir / capsule.name
assert sftp.exists(str(target)), "Target files does not exist!"
sftp.remove(str(target))
assert not sftp.exists(str(target)), "Removed file still exists!"
For a pysftp only approach to delete non-empty directories, you can use con.walktree
to recursively delete all regular files while building a list of subdirectories to delete after the files.
You can’t directly delete the directories from walktree
since it visits the deeper levels last, and you need the opposite.
After the walktree
runs you can iterate (in reverse) over the list of directories and rmdir
each one.
Note that in the code below fcallback=con.remove
so walktree will call remove(remotepath)
for each file recursively.
On the other hand, dcallback=dirs.append
so for each directory will will execute dirs.append(directory_remote_path)
, effectively building the list of directories to delete.
import os
import pysftp
sftp_host = os.environ[ 'SFTP_HOST' ]
sftp_username = os.environ[ 'SFTP_USERNAME' ]
sftp_password = os.environ[ 'SFTP_PASSWORD' ]
con = pysftp.Connection(sftp_host, username=sftp_username, password=sftp_password)
dirs = ['/root/backup/data']
con.walktree(dirs[0], fcallback=con.remove, dcallback=dirs.append, ucallback=con.remove, recurse=True)
print(dirs)
for d in reversed(dirs):
print("Delete directory", d)
con.rmdir(d)
con.close()
I am creating a backup script using pysftp module. I am able to upload
and download files. When i am trying to Delete a directory with some
contents i got an exception.This is what i tried
con = pysftp.Connection('192.168.0.40',username='root',password='clado123')
con.chdir('/root/backup')
con.pwd
con.listdir()
['data', 'test']
data - directory is not empty.
test - directory is empty.
con.rmdir('test')
con.listdir()
['data']
con.rmdir('data')
OSError: Failure
Can any one suggest me a way to solve this problem?
rmdir(remotepath)
found at the documenation http://pysftp.readthedocs.io/en/release_0.2.8/pysftp.html#pysftp.Connection.rmdir
I have find out a way. There is method called ‘execute’ in the pysftp connection object. We can execute commands on remote server using this method.
con.execute('rm -rf /root/backup/data')
con.listdir()
[]
remove
all the files from directory and then use rmdir
to remove empty directory. Works for me.
def clean_dir(sftp, dir, files):
assert sftp.isdir(str(dir)), "Outbox does not exist!"
assert files.is_dir(), "Source directory does not exist!"
for capsule in list(files.iterdir()):
target = dir / capsule.name
assert sftp.exists(str(target)), "Target files does not exist!"
sftp.remove(str(target))
assert not sftp.exists(str(target)), "Removed file still exists!"
For a pysftp only approach to delete non-empty directories, you can use con.walktree
to recursively delete all regular files while building a list of subdirectories to delete after the files.
You can’t directly delete the directories from walktree
since it visits the deeper levels last, and you need the opposite.
After the walktree
runs you can iterate (in reverse) over the list of directories and rmdir
each one.
Note that in the code below fcallback=con.remove
so walktree will call remove(remotepath)
for each file recursively.
On the other hand, dcallback=dirs.append
so for each directory will will execute dirs.append(directory_remote_path)
, effectively building the list of directories to delete.
import os
import pysftp
sftp_host = os.environ[ 'SFTP_HOST' ]
sftp_username = os.environ[ 'SFTP_USERNAME' ]
sftp_password = os.environ[ 'SFTP_PASSWORD' ]
con = pysftp.Connection(sftp_host, username=sftp_username, password=sftp_password)
dirs = ['/root/backup/data']
con.walktree(dirs[0], fcallback=con.remove, dcallback=dirs.append, ucallback=con.remove, recurse=True)
print(dirs)
for d in reversed(dirs):
print("Delete directory", d)
con.rmdir(d)
con.close()