user5354933
user5354933

Reputation:

Is it possible to print columnized output with os.listdir()?

I'm looking to create two columns with os.listdir. Code is standard listdir().

for f in os.listdir(os.curdir):
                print f

Output looks like as follows:

file1
file2
file3
file4

But I'm trying to achieve:

file1    file3
file2    file4

Is that (easily) achievable with os.listdir()?

Upvotes: 1

Views: 572

Answers (5)

user2314737
user2314737

Reputation: 29407

This will print the output of os.listdir() in columns taking care of computing the number of columns by splitting the terminal's width given by the environment variable COLUMNS.

The result is similar to the customary output of ls and it works on iPython and Jupyter Notebooks.

import os
import shutil

def list_files(directory):
    files = sorted(os.listdir(directory))
    max_filename_length = max(len(file) for file in files)  # Get the maximum length of filenames

    terminal_width = shutil.get_terminal_size().columns # int(os.getenv('COLUMNS', 80)) 
    min_column_width = max_filename_length + 2  # minimum width for each column

    columns = max(1, terminal_width // min_column_width)  # adjust the number of columns based on terminal width
    rows = -(-len(files) // columns)  # ceiling division to get # of rows (same as ceil(len(files) / columns))

    for i in range(rows):
        row = ''
        for j in range(columns):
            index = j * rows + i
            if index < len(files):
                filename = files[index]
                row += filename.ljust(max_filename_length + 2)  # adjust spaces for alignment
        print(row)

!rm -rf test;mkdir test; for i in {1..100..10};do touch test/file$i;done;touch test/file22looooongfile

# Usage
#list_files(dir_name)
list_files('test')
# Output:
# file1               file21              file31              file51               file71              file91              
# file11              file22looooongfile  file41              file61               file81   

Compared to the output of ls in IPython:

!ls test
# file1         file21              file31          file51          file71          file91
# file11        file22looooongfile  file41          file61          file81

The ls command in Jupyter Notebooks seems to pack the columns better by adapting each columns's width to the width of its largest element.

Upvotes: 0

Muthuraj S
Muthuraj S

Reputation: 107

Try this,

for i,k in zip(os.listdir(os.curdir)[0::2], os.listdir(os.curdir)[1::2]): print i,k

Upvotes: 0

M. Galczynski
M. Galczynski

Reputation: 634

You can do it easily using function pairwise from this anwser

def pairwise(iterable):
    a = iter(iterable)
    return izip(a, a)

for f1, f2 in pairwise(os.listdir(os.curdir)):
    print f1 + '\t' + f2

Upvotes: 0

Jean-Fran&#231;ois Fabre
Jean-Fran&#231;ois Fabre

Reputation: 140276

os.listdir just returns a list, doesn't print it nicely like ls -C2 would do (note that you don't need python for that if you have ls in your system)

You could do it this way for 2 colums:

import os,itertools

dl=os.listdir(".")

for t in itertools.zip_longest(dl[::2],dl[1::2],fillvalue=""):
    print("{:<20} {:<20}".format(*t))

that would interleave the values together (with zip_longest to avoid forgetting an odd one) and format using 20 spaces for each value.

The general case for any number of columns could be:

import os,itertools

dl=os.listdir(".")

ncols = 3

for t in itertools.zip_longest(*(dl[i::ncols] for i in range(ncols)),fillvalue=""):
    print(("{:<20}"*ncols).format(*t))

(generating ncols shifted lists, interleaving them, and generating the format accordingly)

Upvotes: 2

xystum
xystum

Reputation: 1009

No, it is not possible with os.listdir(). You may have to conside other options like How to print a list more nicely?.

Upvotes: 0

Related Questions