“ls” is unix utility that lists the files and directories in the current path or a user passed path. In this post we will explore how to achive such a basic implementation if it using python. Lets explore the ls command line utility.

Some basic information

First, we execute ls command line utility to get some preliminary information of a directory. Here is an example of the output from the ls command on a sample directory.


Apurvas-MacBook-Pro:Mango apurva$ ls
Mango.db	app.py		config.py	model.py	sample_data.txt	src		templates

In order to accomplish this in python, you would need to import the built-in standard library os and pass a directorty path name to the function listdir()

import os

def show_items_in_(path):
  for entry in os.listdir(path):
    print(f'{entry}', end="	")
show_items_in_(".")
#=> 
Apurvas-MacBook-Pro:Mango apurva$ python3.7 ls.py 
config.py ls.py Mango.db model.py app.py templates sample_data.txt src 

#πŸ€“ Formatting the ouput to match exactly like the native unix tool is left as an exercise for the reader. (Read about python f-strings)

A tad bit more details

Lets try another option ls -l to see the file listing with more details.


Apurvas-MacBook-Pro:Mango apurva$ ls -l
total 24
-rw-r--r--  1 apurva  staff    0 Feb 28 13:14 Mango.db
-rw-r--r--  1 apurva  staff   40 Mar  5 22:15 app.py
-rw-r--r--  1 apurva  staff    0 Feb 28 13:13 config.py
-rw-r--r--@ 1 apurva  staff  138 Mar  5 22:10 ls.py
-rw-r--r--  1 apurva  staff   80 Mar  5 22:15 model.py
-rw-r--r--  1 apurva  staff    0 Feb 28 13:14 sample_data.txt
drwxr-xr-x  2 apurva  staff   64 Feb 28 13:15 src
drwxr-xr-x  2 apurva  staff   64 Feb 28 13:15 templates

In the above output from ls -l we get a lot more details like file permissions, the number of links or directorie, owner name, group name, file size (bytes), and time of modification apart from the name of the file.

In python, we can start with separating out files and directories. This can be achieved by passing the output of os.listdir() to the functions os.path.isfile() and os.path.isdir()

def show_only_files_in_(path):
  for entry in os.listdir(path):
    if os.path.isfile((entry)):
      print(f'{entry}')
#=> config.py ls.py Mango.db model.py app.py sample_data.txt 

def show_only_dirs_in_(dir_path):
  for entry in os.listdir(dir_path):
    if os.path.isdir((entry)):
      print(f'{entry}')
#=> templates src 

#πŸ€“What other cool operations can we run from the os.path class? (Read the documentation os-path-doc)

As you might have observed, we are able to glean a lot more information from the output of the command ls -l. We can get similar details about a file/directory using the os.stat() function. We also be importing the stat library to make sense of the output from os.stat().

import os

def show_stats_of_items_in(path):
    total = 0
    for entry in os.listdir(path):
        statinfo = os.stat(entry)
        print(f'{statinfo} ')
#=> Apurvas-MacBook-Pro:Mango apurva$ python3.7 ls.py 
config.py os.stat_result(st_mode=33188, st_ino=8605068710, st_dev=16777220, st_nlink=1, st_uid=501, st_gid=20, st_size=20, st_atime=1551855990, st_mtime=1551855990, st_ctime=1551855990) 
...
...
src os.stat_result(st_mode=16877, st_ino=8605068718, st_dev=16777220, st_nlink=2, st_uid=501, st_gid=20, st_size=64, st_atime=1551896296, st_mtime=1551388533, st_ctime=1551388533) 

The os.stat() gives us a lot of details about the path passed to it. Let’s decode a few of the fields to make some sense out of it for us mortals.

import os
import stat

 def show_stats_of_items_in(path):
    for entry in os.listdir(path):
        statinfo = os.stat(entry)
        print(f'{stat.filemode(statinfo.st_mode)} ', end="")
        print(f'{entry}')
=#> Apurvas-MacBook-Pro:Mango apurva$ python3.7 ls.py 
-rw-r--r-- config.py
-rw-r--r-- ls.py
-rw-r--r-- Mango.db
-rw-r--r-- model.py
-rw-r--r-- app.py
drwxr-xr-x templates
-rw-r--r-- sample_data.txt
drwxr-xr-x src

As a keen observer, you might have noticed that we have to first make a call to os.listdir() to get all the file/directory listings and then another call to os.stat() to get further details about them. Woudn’t it be better if we can get both results in the same pass? Fortunatley in python3.6 and above you can, using the function os.scandir()

def show_stats_of_items_in(path):
    total = 0
    for entry in os.scandir():
        print(f'{stat.filemode(entry.stat().st_mode)} ', end="")
        print(f'{entry.name}')
=#> Apurvas-MacBook-Pro:Mango apurva$ python3.7 ls.py 
-rw-r--r-- config.py
-rw-r--r-- ls.py
-rw-r--r-- Mango.db
-rw-r--r-- model.py
-rw-r--r-- app.py
drwxr-xr-x templates
-rw-r--r-- sample_data.txt
drwxr-xr-x src

#πŸ€“ Formatting the ouput to match exactly like the output of the ls -l is left as an exercise for the reader. (Read about interpreting os.stat() attributes)

Hope you had fun reading this and it inspires you to dig more into both Python and Unix utilities. I will update with a link to my implementation of ls here as well.