Reputation: 3341
I am trying to list files and its modification time recursively under a directory using pysftp. The problem is, it shows file doesn't exist for all files, but not for directories.
Here is my code:
class SftpOps:
def __init__(self):
config = ConfigManager()
host = config.getSftpUrl()
port = config.getSftpPort()
user = config.getSftpUsername()
password = config.getSftpPassword()
self.source = config.getSourceDirRelativePath()
cnopts = pysftp.CnOpts()
cnopts.hostkeys.load('host_key')
self.sftp = pysftp.Connection(
host, port=port, username=user, password=password, cnopts=cnopts)
def downloadSourceDir(self):
print(self.sftp.listdir())
self.sftp.walktree(self.source, self.fileModifiedTimeCheck,
self.dirModifiedTimeCheck, self.fileModifiedTimeCheck, recurse=True)
self.sftp.close()
def fileModifiedTimeCheck(self, filepath):
filepath = os.path.join(self.source, filepath)
try:
for attr in self.sftp.listdir_attr(filepath):
print(f"{filepath}: {attr.st_atime}")
except FileNotFoundError as err:
print(f"No file at: {filepath}, failed with err: {err}")
except OSError as err:
print("OS error: {0}".format(err))
except:
print("Unexpected error:", sys.exc_info()[0])
raise
def dirModifiedTimeCheck(self, filepath):
filepath = os.path.join(self.source, filepath)
try:
for attr in self.sftp.listdir_attr(filepath):
print(f"{filepath}: {attr.st_atime}")
filepath = "tmp/"+filepath
except FileNotFoundError:
print(f"No dir at: {filepath}")
except OSError as err:
print("OS error: {0}".format(err))
except:
print("Unexpected error:", sys.exc_info()[0])
raise
# class LogOps:
# def __init__(self):
# class EmailOps:
# def __init__(self):
print("=========================================")
test_obj = SftpOps()
test_obj.downloadSourceDir()
print("=========================================")
When I try this for a directory with the below structure
It gives the errors as:
=========================================
['.DS_Store', 'about-me.html', 'favicon.ico', 'index.html', 'test']
No file at: /Downloads/techtuft/.DS_Store, failed with err: [Errno 2] No such file
No file at: /Downloads/techtuft/about-me.html, failed with err: [Errno 2] No such file
No file at: /Downloads/techtuft/favicon.ico, failed with err: [Errno 2] No such file
No file at: /Downloads/techtuft/index.html, failed with err: [Errno 2] No such file
/Downloads/techtuft/test: 1569165379
No file at: /Downloads/techtuft/test/style.css, failed with err: [Errno 2] No such file
=========================================
Please note, how it doesn't show error for the directory "test".
Upvotes: 2
Views: 2246
Reputation: 202494
You cannot use Connection.listdir_attr
for files.
You should use Connection.stat
.
Though that would be terribly inefficient anyway. You better copy over the implementation of walktree
function and make it call Connection.listdir_attr
instead of Connection.listdir
. That way you obtain timestamps for all files in the directory in a single call to the server, en masse, instead of retrieving them inefficiently file-by-file.
See also Python SFTP download files older than x and delete networked storage.
Upvotes: 1
Reputation: 5454
So it seems that the method listdir_attr
displays current entries in a directory but does not handle special entries such as paths containing .
and ..
. Make reference here from the docs. This is why the test
folder was not included into your error message.
You can however use the lstat
method to identify files:
>>> for i in sftp.listdir():
... lstatout=str(sftp.lstat(i)).split()[0]
... if 'd' not in lstatout: #do something
...
Upvotes: 0