# python 2 or 3
# Author: Gribouillis for the python forum at www.daniweb.com
# licence: public domain
# use this code freely.
# 03 Mar '15: version 0.2.1, bug fix for empty list and added file, flush args.
# 21 Dec '13: version 0.1, bug fix and added re-calculation of ncols.
from __future__ import print_function
from distutils.version import StrictVersion # pep 386
import prettytable as ptt # pip install prettytable
import sys
assert StrictVersion(ptt.__version__) >= StrictVersion('0.7') # for PrettyTable.vrules property

__version__ = '0.2.1'

def example_list():
    """Return sorted list of python module names"""
    import pkgutil
    L = list(sys.builtin_module_names)
    L.extend(t[1] for t in pkgutil.iter_modules())
    return sorted(L)

def print_multicolumn(alist, ncols, vertically=True, file=None, flush=False):
    """Print a list of strings in several columns
    alist: the list to print
    ncols: the desired number of columns in output
    vertically: whether the list items must be enumerated column by
                column or row by row, defaults to True.
    file: a file-like object (stream), defaults to sys.stdout.
    flush: whether to forcibly flush the stream, defaults to False.
    L = alist
    if not L:
        if flush(): file.flush()
    # incompressible number of rows without adding columns.
    nrows = - ((-len(L)) // ncols)
    # the number of columns may be reducible for that many rows.
    ncols = - ((-len(L)) // nrows)
    t = ptt.PrettyTable([str(x) for x in range(ncols)])
    t.header = False
    t.align = 'l'
    t.hrules = ptt.NONE
    t.vrules = ptt.NONE
    r = nrows if vertically else ncols
    chunks = [L[i:i+r] for i in range(0, len(L), r)]
    chunks[-1].extend('' for i in range(r - len(chunks[-1])))
    if vertically:
        chunks = zip(*chunks)
    for c in chunks:
    if file is None: file = sys.stdout
    print(t, file=file)
    if flush: file.flush()
if __name__ == '__main__':
    L = example_list()
    print_multicolumn(L, 4, vertically = True)
""" my output -->
  CDROM                 aifc              heapq                   readline       
  CommandNotFound       antigravity       hmac                    reprlib        
  DLFCN                 apt               html                    resource       
  DistUpgrade           apt_clone         http                    rlcompleter    
  IN                    apt_inst          icu                     runpy          
  LanguageSelector      apt_pkg           idlelib                 sandbox    
3 Years
Discussion Span
Last Post by Gribouillis

This can actually be used to mimick the action of the ls command with colorful output. The following code lists the user's home directory with colors:

from termcolor import colored # pip install termcolor
import sys
if sys.platform == 'win32':
    from colorama import init # pip install colorama
import os
import stat

def color_code(filename):
        mode = os.lstat(filename).st_mode
    except OSError:
    if stat.S_ISDIR(mode):
        return 'blue'
    elif stat.S_ISLNK(mode):
        return 'cyan'
    elif stat.S_ISFIFO(mode) or stat.S_ISBLK(mode):
        return 'yellow'
    elif mode & (stat.S_IXUSR):
        return 'green'
    elif filename.endswith((".tar", ".zip", ".deb", ".rpm", ".gz")):
        return 'red'
    elif filename.endswith((".jpg", ".gif", ".png", ".tiff", ".mp3", ".ogg", ".wav")):
        return 'magenta'

def listdir_color(directory):
    L = sorted(os.listdir(directory), key = lambda s: s.lower())
    for i, name in enumerate(L):
        fn = os.path.join(directory, name)
        col = color_code(fn)
        if col is not None:
            L[i] = colored(name, col)
    return L

if __name__ == '__main__':
    L = listdir_color(os.path.expanduser('~'))
    print_multicolumn(L, 4)

It even works in the ipython notebook !

Also notice that (partial) pure python implementations of ls already exist. See the pycoreutils package :)

Edited by Gribouillis

Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.