Bringing Linux Power To Windows By Building Custom Commands

0
2

This brief tutorial will help you build Python versions of two vital Linux commands—Is and grep.

As developers, we often find ourselves switching between Linux and Windows environments. While Windows has made strides with PowerShell and WSL (Windows Subsystem for Linux), sometimes you just want the familiar UNIX-like commands available natively. That is why I created Python-based implementations of two essential Linux commands—ls and grep—and deployed them as native Windows executables.

Why recreate these commands?

Windows has dir instead of ls and findstr instead of grep, but their syntax and behaviour differ significantly from their UNIX counterparts. For developers who work across platforms, having consistent commands can significantly improve workflow efficiency. By creating Python versions and converting them to executables with PyInstaller, we get:

  • Cross-platform consistency: Same syntax across Windows and Linux.
  • Easy customisation: Python code is simple to modify.
  • Native performance: Compiled executables run directly without Python interpreter overhead.
  • System-wide availability: Placed in System32 for global access.

The ls command: Windows directory listing, UNIX style

The ls command lists directory contents with UNIX-like formatting and options. Let’s break down the key components.

The core functions are:

get_file_attributes(filepath)

def get_file_attributes(filepath):

“””Get Windows file attributes”””

This function retrieves Windows-specific file attributes (Hidden, System, ReadOnly, Archive) using the stat module. It returns a compact string representation like ʽHSRʼ for a hidden, system, read-only file.

format_permissions(mode)

python

def format_permissions(mode):

“””Format file permissions for Windows”””

The above function converts file mode bits into UNIX-style permission strings (e.g., -rwx). While Windows permissions are more complex than UNIX, this provides a familiar visual representation showing directory status and basic read/write/execute flags.

format_size(size)

def format_size(size):

“””Format file size in human readable format”””

This function transforms raw byte counts into human-readable formats (B, KB, MB, GB, TB). This is essential for the -h option, making large file sizes easier to understand at a glance.

get_file_info(path, filename)

def get_file_info(path, filename):

“””Get file information”””

The information gatherer collects all metadata for a single file or directory including size, modification time, permissions, and Windows attributes. It returns a structured dictionary for easy processing.

list_directory(path, args)

def list_directory(path, args):

“””List directory contents”””

This is the main orchestrator that reads directory contents, filters hidden files (unless -a is specified), applies sorting based on flags (-t for time, –S for size), and delegates to the appropriate display function.

display_long_format(file_infos, args) and display_short_format(file_infos, args): These functions handle output formatting. Long format (-l) shows detailed information in columns, while short format displays files in a multi-column layout optimised for terminal width.

Supported options are:

  • -a, –all: Show hidden files (including those starting
    with .)
  • -l, –long: Long listing format with permissions, size, and date
  • -h, –human-readable: Display sizes in KB, MB, GB instead of bytes
  • -t, –time: Sort by modification time
  • -S, –size: Sort by file size
  • -r, –reverse: Reverse sort order
  • -F, –classify: Append indicators (/ for directories, * for executables)
  • -1, –one: One file per line
  • –attrs: Show Windows file attributes (H, S, R, A)

The usage of the Is command is shown in Figures 1 and 2.

Figure 1: Use of ls command
File listing according to date
Figure 2: File listing according to date

The grep command: Pattern matching made simple

The grep command searches for text patterns in files or piped input, bringing UNIX text-processing power to Windows.

The core functions are:

grep(pattern, lines, case_sensitive, invert, count_only, show_line_num)

python

def grep(pattern, lines, case_sensitive=True, invert=False,

count_only=False, show_line_num=False):

“””Search for pattern in lines.”””

The heart of the tool iterates through input lines, applies regex pattern matching with optional flags, and outputs matching results. The invert flag enables negative matching (showing lines that DON’T match), while count_only returns just the number of matches.

main()

def main():

“””Main grep function.”””

This function handles command-line argument parsing, determines input source (file or stdin), and invokes the grep function with appropriate parameters. It intelligently detects whether the input is piped or from a file.

Supported options are:

  • -i: Case-insensitive search
  • -v: Invert match (show non-matching lines)
  • -c: Count matching lines only
  • -n: Show line numbers

Usage examples for grep are shown in Figure 3.

Grep command
Figure 3: Grep command

Deployment: From Python to system command

Step 1: Install PyInstaller:

pip install pyinstaller

Step 2: Create executables:

pyinstaller --onefile ls.py

pyinstaller --onefile grep.py

This generates standalone executables in the dist/ folder.

Step 3: Deploy to System32:

# Run as Administrator

copy dist\ls.exe C:\Windows\System32\

copy dist\grep.exe C:\Windows\System32\

Placing the executables in System32 makes them available system-wide in any command prompt or PowerShell session without path configuration.

Advantages and limitations of creating these commands

Advantages

  • Familiar UNIX syntax for cross-platform developers
  • Lightweight and fast
  • Easy to customise and extend
  • No dependencies (compiled executables are standalone)

Limitations

  • Windows permission model differs from UNIX; so permission strings are simplified.
  • Some advanced ls and grep options are not implemented (can be added as needed).
  • Large directory listings may be slower than the native dir command.

All the code has been placed at https://github.com/mohitraj/commands. Do check it out.

LEAVE A REPLY

Please enter your comment!
Please enter your name here