summaryrefslogtreecommitdiff
path: root/ftp-list.py
diff options
context:
space:
mode:
authorPeter Wu <lekensteyn@gmail.com>2013-07-13 12:36:10 +0200
committerPeter Wu <lekensteyn@gmail.com>2013-07-13 12:36:10 +0200
commita9ae058b06ef0236fc64237e5c6dc7b779e13468 (patch)
treeff91991e89b0bb18f37cfc2e8beeb9fb29c2079a /ftp-list.py
parenta4471f71aad10433725161dff9ac39b8f23c4d77 (diff)
downloadscripts-a9ae058b06ef0236fc64237e5c6dc7b779e13468.tar.gz
ftp*: python3 compat, SIZE fixes, MLSD support
Set binary mode before requesting size, do not exit program if size() fails. Support MLSD mode for ftp-list.py (mostly copied from ftp.py)
Diffstat (limited to 'ftp-list.py')
-rwxr-xr-xftp-list.py89
1 files changed, 82 insertions, 7 deletions
diff --git a/ftp-list.py b/ftp-list.py
index 1b65832..3d7a21b 100755
--- a/ftp-list.py
+++ b/ftp-list.py
@@ -6,9 +6,14 @@
# Prepend directory name to files and list files:
# awk '/^Directory/{if($0 != "Directory /")dir=substr($0, index($0, "/"))}/^-/{n=index($0,$9);print substr($0,1, n - 1) dir "/" substr($0,n)}'
+from __future__ import print_function
+
import sys
from ftplib import FTP
import re
+from datetime import datetime, timezone, date
+
+use_list = False
user = "anonymous"
passwd = "anon"
@@ -71,23 +76,86 @@ patt_list = re.compile(r"""
$
""", re.VERBOSE)
+def queue_dir(cwd, name):
+ if cwd == "/":
+ dir = "/" + name
+ else:
+ dir = cwd + "/" + name
+ print("Queuing", dir, file=sys.stderr)
+ dirs.append(dir)
+
+# LIST handler
def get_ls_processor(cwd):
def process_dir(line):
print(line)
if line[0] == 'd':
m = patt_list.match(line)
name = m.group(1)
- if cwd == "/":
- dir = "/" + name
- else:
- dir = cwd + "/" + name
- print("Queuing", dir, file=sys.stderr)
- dirs.append(dir)
+ queue_dir(cwd, name)
# elif line[0] == 'l':
# m = patt_list.match(line)
# print("Link", m.group(2))
return process_dir
+# MLSD handler
+def format_perms(mode):
+ """Turns a numeric UNIX mode into human-readable form
+ """
+ str = ""
+ for i in range(0, 3):
+ o = 0o100 >> (3 * i)
+ str += "r" if mode & (4 * o) else "-"
+ str += "w" if mode & (2 * o) else "-"
+ if mode & (0o4000 >> i): # setuid, setgid or sticky bit
+ if o == 0o001: # "world"
+ str += "t" if mode & o else "T"
+ else:
+ str += "s" if mode & o else "S"
+ else:
+ str += "x" if mode & (1 * o) else "-"
+ return str
+
+def format_type_fact(type):
+ if type == "file":
+ return "-"
+ elif type in ("cdir", "pdir", "dir"):
+ return "d"
+ # TODO: handle OS.name=type
+ else:
+ return "?"
+
+def dt_from_ftp(timeval):
+ return datetime.strptime(timeval, "%Y%m%d%H%M%S").replace(tzinfo=timezone.utc)
+
+def format_mlsd(name, facts):
+
+ if "type" in facts:
+ mode_desc = format_type_fact(facts["type"])
+ else:
+ mode_desc = "?"
+
+ if "unix.mode" in facts:
+ perm = int(facts["unix.mode"], 8)
+ mode_desc += format_perms(perm)
+ else:
+ mode_desc += "?" * 9
+
+ user = "?" if not "unix.owner" in facts else facts["unix.owner"]
+ group = "?" if not "unix.group" in facts else facts["unix.group"]
+ size = "" if not "size" in facts else int(facts["size"])
+
+ modtime = 0 if not "modify" in facts else dt_from_ftp(facts["modify"])
+ if date.today().year == modtime.year:
+ date_str = modtime.strftime("%b %d %H:%M")
+ else:
+ date_str = modtime.strftime("%b %d %Y")
+
+ line = mode_desc + " "
+ #line += " {links:4s}".format(links=-1)
+ line += " {user:8s} {group:8s} {size:8}".format(user=user, group=group, size=size)
+ line += " " + date_str + " " + name
+ return line
+
with FTP() as ftp:
ftp.connect(host, port)
ftp.login(user, passwd)
@@ -96,5 +164,12 @@ with FTP() as ftp:
dir = dirs.pop()
ftp.cwd(dir)
print("Directory", ftp.pwd())
- ftp.retrlines('LIST', get_ls_processor(dir))
+ if use_list:
+ ftp.retrlines('LIST', get_ls_processor(dir))
+ else:
+ for name, facts in ftp.mlsd():
+ if name not in (".", ".."):
+ print(format_mlsd(name, facts))
+ if facts["type"] == "dir":
+ queue_dir(dir, name)
print("Queue size:", len(dirs), file=sys.stderr)