- #!/usr/bin/env python
- """
- tdir - Display Formatted Directory Listings
- Copyright (c) 2001-2018 TundraWare Inc., All Rights Reserved.
- """
-
- # python Library Imports
-
- import getopt
- import os
- import sys
-
- # Version info
-
- VERSION = "$Id: tdir,v 1.73 2018/06/17 00:00:00 tundra Exp $"
-
-
- # Supporting Functions
-
- # Found at: http://stackoverflow.com/questions/566746/how-to-get-console-window-width-in-python
-
- def GetTerminalSize():
-
- env = os.environ
- def ioctl_GWINSZ(fd):
-
- try:
- import fcntl, termios, struct, os
- cr = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ, '1234'))
-
- except:
- return
-
- return cr
-
- cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2)
- if not cr:
-
- try:
- fd = os.open(os.ctermid(), os.O_RDONLY)
- cr = ioctl_GWINSZ(fd)
- os.close(fd)
-
- except:
- pass
-
- if not cr:
- cr = (env.get('LINES', 25), env.get('COLUMNS', 80))
-
- ### Use get(key[, default]) instead of a try/catch
- #try:
- # cr = (env['LINES'], env['COLUMNS'])
- #except:
- # cr = (25, 80)
-
- return int(cr[1]), int(cr[0])
-
- # End of 'GetTerminalSize()'
-
-
- # Output formatting constants.
-
- OWIDTH = 80 # Default output width fixed for non-*NIX systems
-
- if os.name == 'posix': # On *NIX get the current window parameter instead
- OWIDTH = GetTerminalSize()[0] - 1
-
- COLWIDTH = 19 # Width of each column
- TWIDTH = COLWIDTH - 1 # Text width
- MAXCOL, INDENT = divmod(OWIDTH, COLWIDTH) # No of output cols & indent
- PAD = " " # Padding character
- SEP = "." # Filename "extension" separator
- TRUNC = "^" # Character indicating name truncation
- DOTFILE = '.' # Dotfiles start with this
-
- # Defaults
-
- RECURSE = False # No recursion
- SHOWDIR = True # Show directories in listing
- SHOWDOT = True # Show dotfiles in listing
- SHOWFILE = True # Show files in listing
- SORTBYEXT = True # Sort file names by extension
-
-
- def OrderByExtension(list):
- ExtList = {}
- ExtList[""] = [] # List of files with no extension
-
- for x in list:
- y = x.rfind(SEP)
- if not y: # Handle special case of 'dot file' type files
- ext = ""
- name = x
- elif y != -1: # File has extension
- ext = x[y:]
- name = x[:y]
- if ext not in ExtList:
- ExtList[ext]= []
- else: # File has no extension
- ext = ""
- name = x
- ExtList[ext].append(name)
-
- return ExtList
-
-
- def OutputColumns(list, ISDIRLIST):
- col = 0
- if ISDIRLIST: # If listing directory, printed length
- BIAS = 2 # is longer by BIAS chars than actual name
- else:
- BIAS = 0
- for x in list:
- if col == MAXCOL:
- sys.stdout.write("\n")
- col = 0
- if len(x) > TWIDTH - BIAS:
- x = x[:TWIDTH - BIAS - 1 ] + TRUNC
- if ISDIRLIST:
- x = "[" + x + "]"
- if col == 0:
- sys.stdout.write(INDENT * PAD)
- sys.stdout.write(x + (COLWIDTH - len(x)) * PAD)
- col += 1
- sys.stdout.write("\n\n")
-
-
- def DisplayOutput(dir, DirList, FileList):
- if (dir[-1] != "/") and (dir[-1] != "\\"):
- DIREND = "/\n"
- else:
- DIREND = "\n"
- sys.stdout.write(dir.replace("\\", "/") + DIREND)
-
- if SHOWDIR or SHOWFILE:
- sys.stdout.write("\n")
-
- if len(DirList) > 0:
- DirList.sort()
- OutputColumns(DirList, True)
-
- if len(FileList) > 0:
- if SORTBYEXT:
- ExtList = OrderByExtension(FileList)
- Ext = list(ExtList.keys())
- Ext.sort()
- for x in Ext:
- FileList = ExtList[x]
- if len(FileList) > 0:
- FileList.sort()
- sys.stdout.write("(" + x + ")\n")
- OutputColumns(FileList, False)
-
- else:
- FileList.sort()
- OutputColumns(FileList, False)
-
-
-
- def BuildFileList (args, dir, files):
- DirList = []
- FileList = []
- for x in files:
- df = x.startswith(DOTFILE) # Track whether name is a 'dotfile/dir'
- if (dir[-1] == '/') or (dir[-1] == '\\'): # This if/else sequence necessary because
- dirstring = dir + x # 'tdir /' did not properly report directories
- else: # on WinDoze32 systems which appears to
- dirstring = dir + "/" + x # handle '//' or '\/' in files names very well.
- if os.path.isdir(dirstring):
- if SHOWDIR and (not df or SHOWDOT):
- DirList.append(x)
- elif SHOWFILE and (not df or SHOWDOT):
- FileList.append(x)
- DisplayOutput(dir, DirList, FileList)
-
-
- def Usage():
- UsageInfo = (
- ("tdir " + VERSION.split()[2] +
- " - Copyright (c) 2001-2018 TundraWare Inc., All Rights Reserved. \n", ""),
- (" usage: tdir [-DRdefhtv] [-c #] [-s c] [-w #] [dir...] where,\n\n", ""),
- ("-D", "Do not display dot files\n"),
- ("-R", "Recurse down each named directory tree\n"),
- ("-c #", "Column width\n"),
- ("-d", "Do not display directories in output\n"),
- ("-e", "Do not sort files by extension\n"),
- ("-f", "Do not display files in output\n"),
- ("-h", "Display this help information\n"),
- ("-s c", "Separator character\n"),
- ("-t", "Display only the directory tree - same as -Rdf\n"),
- ("-v", "Display tdir version information\n"),
- ("-w #", "Width of output\n"),
- ("dir...", "List of directories to display. Defaults to ./\n")
- )
-
- for x, y in UsageInfo:
- if len(x) < 10: # Only indent for the actual argument info
- sys.stdout.write(10 * PAD)
- sys.stdout.write(x)
- sys.stdout.write((8 - len(x)) * PAD)
- sys.stdout.write(y)
-
- # Program entry and command line processing
-
- try:
- opts, args = getopt.getopt(sys.argv[1:], '-DRc:edfhs:tvw:')
- except getopt.GetoptError:
- Usage()
- sys.exit(2)
-
- for opt, val in opts:
- if opt == "-D":
- SHOWDOT = False
- if opt == "-R":
- RECURSE = True
- if opt == "-c":
- COLWIDTH = int(val)
- if opt == "-d":
- SHOWDIR = False
- if opt == "-e":
- SORTBYEXT = False
- if opt == "-f":
- SHOWFILE = False
- if opt == "-h":
- Usage()
- sys.exit(0)
- if opt == "-s":
- SEP = val[0]
- if opt == "-t":
- RECURSE = True
- SHOWDIR = False
- SHOWFILE = False
- if opt == "-v":
- sys.stdout.write(VERSION + "\n")
- sys.exit(0)
- if opt == "-w":
- OWIDTH = int(val)
-
- if OWIDTH < COLWIDTH:
- sys.stdout.write("Huh? Column width exceeds output width!\n")
- sys.exit(2)
-
- TWIDTH = COLWIDTH - 1 # Text width
- MAXCOL, INDENT = divmod(OWIDTH, COLWIDTH) # No of output cols & indent
-
- if len(args) == 0: # Default to local directory if none given
- args = ["./"]
-
- for root in args:
- if not os.path.isdir(root):
- sys.stdout.write(root + " is not a directory!\n")
- sys.exit(2)
- if RECURSE:
- for root, dir, files in os.walk(root):
- if root[-1] != os.sep:
- root += os.sep
- print(root)
- else:
- BuildFileList(None, root, os.listdir(root))