Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Distinguish between a file or a directory in paramiko

I'm trying to walk over the contents of a directory and determine whether or not each item is a file or a folder. I can do the solution suggested in this link:

>>> for i in ftp.listdir():
...     lstatout=str(ftp.lstat(i)).split()[0]
...     if 'd' not in lstatout: print i, 'is a file'
... 

This works, yes. As a sidenote, I'm just taking the first character instead of .split(), so str(ftp.lstati(i))[0] != 'd', as this appears to be faster in my admittedly non-scientific testing.

But this seems extremely hacky, so I tried to check out other methods. In the SFTP attributes for a few folders, I see:

<SFTPAttributes: [ size=4096 uid=1002 gid=1002 mode=040755 atime=1358785383 mtime=1359475285 ]>

while in the same for files, I see:

<SFTPAttributes: [ size=72 uid=1002 gid=1002 mode=0100644 atime=1367598914 mtime=1367598914 ]>

So it seems that the mode is 010[permissions] for files, and 040[permissions] for directories (consistent in the few directories I've seen, but can't say it's universal). This seems to be a much better way to get that attribute of the item! But, when I use ftp.stat(i).st_mode, I get a different value – 16877 for the aforementioned directory, and 33188 for the aforementioned file.

What do these mean? Is there a way I can convert that integer to the file mode? (I tried Google, but can't find anything relevant.) Alternatively, is there any good way I can determine this without relying on the str(lstat(i)) function returning a 'd' or not-'d'?

like image 744
pswaminathan Avatar asked Jan 13 '23 10:01

pswaminathan


2 Answers

Paramiko's SFTPAttributes.st_mode can be passed to Python's os.stat for analysis:

for file in ftp_cli.listdir_attr(path):
    is_dir = stat.S_ISDIR(file.st_mode)
    is_link = stat.S_ISLNK(file.st_mode)
    is_file = stat.S_ISREG(file.st_mode)
like image 130
dave Avatar answered Jan 24 '23 03:01

dave


It looks like the high bits do indeed tell you whether it is a file or a directory:

S_ISDIR
S_ISREG

>>> oct(16877)
'040755'
>>> oct(33188)
'0100644'

And likewise:

>>> int('040755', 8)
16877
>>> int('0100644', 8)
33188
like image 23
sberry Avatar answered Jan 24 '23 03:01

sberry