15

I'd like to delete all the files in a given directory on a remote server that I'm already connected to using Paramiko. I cannot explicitly give the file names, though, because these will vary depending on which version of file I had previously put there.

Here's what I'm trying to do... the line below the #TODO is the call I'm trying where remoteArtifactPath is something like /opt/foo/*

ssh = paramiko.SSHClient()
ssh.load_host_keys(os.path.expanduser(os.path.join("~", ".ssh", "known_hosts")))
ssh.connect(server, username=username, pkey=mykey)
sftp = ssh.open_sftp()

# TODO: Need to somehow delete all files in remoteArtifactPath remotely
sftp.remove(remoteArtifactPath+"*")

# Close to end
sftp.close()
ssh.close()

Any idea how I can achieve this?

Martin Prikryl
  • 167,268
  • 50
  • 405
  • 846
Cuga
  • 17,301
  • 30
  • 108
  • 159

5 Answers5

19

I found a solution: Iterate over all the files in the remote location, then call remove on each of them:

ssh = paramiko.SSHClient()
ssh.load_host_keys(os.path.expanduser(os.path.join("~", ".ssh", "known_hosts")))
ssh.connect(server, username=username, pkey=mykey)
sftp = ssh.open_sftp()

# Updated code below:
filesInRemoteArtifacts = sftp.listdir(path=remoteArtifactPath)
for file in filesInRemoteArtifacts:
    sftp.remove(remoteArtifactPath+file)

# Close to end
sftp.close()
ssh.close()
Cuga
  • 17,301
  • 30
  • 108
  • 159
  • 5
    I suggest using ```os.path.join(remoteArtifactPath, file)``` instead of ```sftp.remove(remoteArtifactPath+file)```, because ```os.path.join()``` is platform independent. Line separators may differ by platform and using os.path.join ensures that paths are generated correctly, regardless of platform. – 9monkeys Jul 17 '12 at 14:23
  • Will this remove hidden files too? – SabirAmeen Oct 24 '18 at 09:00
10

You need a recursive routine since your remote directory may have subdirectories.

def rmtree(sftp, remotepath, level=0):
    for f in sftp.listdir_attr(remotepath):
        rpath = posixpath.join(remotepath, f.filename)
        if stat.S_ISDIR(f.st_mode):
            rmtree(sftp, rpath, level=(level + 1))
        else:
            rpath = posixpath.join(remotepath, f.filename)
            print('removing %s%s' % ('    ' * level, rpath))
            sftp.remove(rpath)
    print('removing %s%s' % ('    ' * level, remotepath))
    sftp.rmdir(remotepath)

ssh = paramiko.SSHClient()
ssh.load_host_keys(os.path.expanduser(os.path.join("~", ".ssh", "known_hosts")))
ssh.connect(server, username=username, pkey=mykey)
sftp = ssh.open_sftp()
rmtree(sftp, remoteArtifactPath)

# Close to end
stfp.close()
ssh.close()
markolopa
  • 351
  • 1
  • 4
  • 6
8

A Fabric routine could be as simple as this:

with cd(remoteArtifactPath):
    run("rm *")

Fabric is great for executing shell commands on remote servers. Fabric actually uses Paramiko underneath, so you can use both if you need to.

ianmclaury
  • 1,158
  • 6
  • 5
  • +1, because in EC2 our OS images defaulted with sftp disabled. (I'm unsure if that's Amazon's default or my company, but the question is irrelevant because I can't get that changed. I did however, still need to remove the file. – Scott Prive Jun 26 '15 at 19:14
2

For @markolopa answer, you need 2 imports to get it working:

import posixpath
from stat import S_ISDIR
broferek
  • 81
  • 3
2

I found a solution, using python3.7 e spur 0.3.20. It is very possible that works with others versions as well.

import spur

shell = spur.SshShell( hostname="ssh_host", username="ssh_usr", password="ssh_pwd")
ssh_session = shell._connect_ssh()

ssh_session.exec_command('rm -rf  /dir1/dir2/dir3')

ssh_session.close()