Sitemap
Parsa Saber

Parsa Saber

Python cooperating with Linux, Implement Linux “ls” command in Python

4 min readSep 29, 2024

--

Press enter or click to view image in full size

Introduction to the ls -l Command in Linux

The ls command is one of the most frequently used commands in Linux to list files and directories. The -l option, which stands for "long listing format," provides detailed information about the files, including permissions, number of links, owner, group, size, and the last modified date and time.

Get Parsa Saber’s stories in your inbox

Join Medium for free to get updates from this writer.

When you execute ls -l in a directory, the output might look something like this:

-rw-r--r--  1 user user  1048576 Jan 01 12:34 example.txt
drwxr-xr-x 2 user user 4096 Jan 01 12:34 my_directory

Each line contains several columns of data:

  • File Type and Permissions: The first character indicates the file type (e.g., - for regular files, d for directories), followed by the file's permission bits.
  • Number of Links: Shows how many links point to the file or directory.
  • Owner: The name of the file’s owner.
  • Group: The group that owns the file.
  • File Size: Displayed in bytes.
  • Last Modified Date: The date and time when the file was last modified.
  • File Name: The name of the file or directory.

Developing a Python Script to Implement the ls -l Command in Linux

In this section, we will walk through the process of developing a Python script that mimics the behavior of the ls -l command in Linux. The script will provide two modes:

  1. Listing files and directories in a simple format.
  2. Displaying detailed file attributes similar to ls -l, including file permissions, owner, group, file size, and modification time.

Below is a breakdown of the steps and explanation of the code implementation.

1. Import Required Libraries

To begin, we need to import several Python libraries:

  • datetime to handle the formatting of timestamps.
  • argparse for command-line argument parsing.
  • sys for accessing command-line arguments.
  • os to interact with the file system.
from datetime import datetime
import argparse
import sys
import os

2. Set the Working Directory

The os.chdir("test") line is used to change the working directory to a folder named test. This is important because we want to list the contents of this directory.

os.chdir("test")

You can change "test" to any directory of your choice.

3. Handle Command-Line Arguments

To allow users to choose between a simple list of files and a detailed listing (similar to ls -l), we use the argparse module. The script supports a -l flag to toggle between the two modes.

  • The store_false action makes the argument return False when the -l flag is used.
  • We use an assertion to limit the number of command-line arguments to a maximum of one.
args = sys.argv[1:]
assert 0 <= len(args) <= 1, "Invalid arguments"
parser = argparse.ArgumentParser(description='Implement Linux ls.', allow_abbrev=False)
parser.add_argument('-l', action='store_false')
args = parser.parse_args()

4. Separate Files and Directories

Using the os.listdir() function, we retrieve the contents of the current directory. We then separate them into two lists: one for folders and one for regular files.

f_files = (os.listdir(os.getcwd()))
folders = [f for f in f_files if os.path.isdir(f)]
files = [f for f in f_files if not os.path.isdir(f)]

5. Implement the Simple ls Listing

If the -l flag is not provided, the script will print the files and directories in a simple format. Directories will be displayed in blue, while files will be in green.

if args.l:
counter = 0
all_files = sorted(f_files, reverse=True)
while all_files:
if counter == 12:
print()
counter = 0
else:
if folders and all_files:
if (a := all_files.pop()) in folders:
print('\033[34m'+a, end=" ")
print('\033[0m', end=" ")
else:
print('\033[32m'+ a, end=" ")
print('\033[0m', end=" ")

This block of code displays the directory and file names in their respective colors.

6. Implement Detailed ls -l Listing

When the -l flag is provided, the script mimics the ls -l behavior, displaying file permissions, owner, group, size, last modification time, and the file name. Directories and files are printed in different colors.

File Permissions Calculation

The file permissions are calculated using the os.stat() function, which provides a file's metadata. The permissions are then converted from octal format to a readable string of rwx (read, write, execute).

pm_number = str(oct(stat.st_mode))
p_number_count = len(pm_number)
prms = pm_number[p_number_count-3:p_number_count]
permissions = ""
for p in prms:
permison = str(bin(int(p)))[-3:]
perm = "rwx"
s = "".join(map(lambda w: w[0] if w[1] != "0" else "-", zip(list(perm), list(permison))))
permissions += s

File Details

The file’s owner, group, size, and last modification time are extracted using os.stat(). The modification time is formatted using datetime.strftime().

time = (datetime.fromtimestamp(float(str(stat.st_birthtime))))
time = str(time.strftime("%b %d %Y"))

Finally, the script prints all the file details in a structured format similar to ls -l.

permisions = "d" + permissions if a in folders else "-" + permissions
print(f'{permissions:10s} {str(stat.st_uid):1s} {str(stat.st_gid):1s} {(stat.st_size):7d} {time:3} {a:3s}')

7. Handling Invalid Commands

The script handles cases where invalid commands or arguments are provided. If the argument count exceeds one, the script will print an error and exit.

else:
print("Invalid command")
exit()

Last Word

By following this approach, we’ve successfully created a Python script that mimics the behavior of the ls -l command. It lists files and directories in both simple and detailed formats. Understanding how to replicate such commands in Python is a great way to deepen your understanding of both Linux and Python’s os and argparse modules.

Feel free to modify the script for different use cases, such as filtering specific file types or sorting by other criteria.

Feel free to visit my GitHub Gist document below ❤️:

--

--