Skip to content
52 changes: 52 additions & 0 deletions implement-shell-tools/cat/cat.py

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your implementation works well, but your code could be improved a bit. Can you see any issues with the code style you could fix?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@LonMcGregor thank you for your feedback on this PR. I have tried to separate the logic using one more additional method and make the main method clean and organised. Can you please review back this PR and approve it so that i could close it if it is sufficient. Thankyou

Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import argparse
import sys


def read_files(paths):
lines = []
for path in paths:
try:
with open(path, "r", encoding="utf-8") as f:
lines.extend(f.read().splitlines())
except OSError as e:
print(f"Error reading {path}: {e}", file=sys.stderr)
sys.exit(1)
return lines


def main():
parser = argparse.ArgumentParser(
prog="display-content-of-a-file",
description="cat is used to display the content of a file or print the content of a file.",
)

parser.add_argument("-n", action="store_true", help="number output lines")
parser.add_argument("-b", action="store_true", help="number non-empty output lines")
parser.add_argument("paths", nargs="+", help="The file path(s) to process")

options = parser.parse_args()

lines = read_files(options.paths)

if options.b:
line_num = 1
for line in lines:
if line.strip():
print(f"{line_num:6} {line}")
line_num += 1
else:
print(line)

elif options.n:
for i, line in enumerate(lines, start=1):
print(f"{i:6} {line}")

else:
for line in lines:
print(line)


if __name__ == "__main__":
main()

#python3 cat.py -b sample-files/*
37 changes: 37 additions & 0 deletions implement-shell-tools/ls/ls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import argparse #for parsing command-line arguments and options
import os #to interact with the os for listing files and handling paths
import sys #Allows interaction with the Py runtime env like reading/writing output,exiting.


def list_directory(directory, show_all, one_per_line):
try:
files = os.listdir(directory)
except Exception as e:
print(f"ls: cannot access '{directory}': {e}", file=sys.stderr)
return 1

if not show_all:
files = [f for f in files if not f.startswith('.')]
files.sort()

if one_per_line:
for file in files:
print(file)
else:
print(' '.join(files))

return 0

def main():
parser = argparse.ArgumentParser(description="A simplified ls implementation.")
parser.add_argument('-1', dest='one_per_line', action='store_true', help='list one file per line')
parser.add_argument('-a', action='store_true', help='include hidden files')
parser.add_argument('directory', nargs='?', default='.', help='directory to list (default: current directory)')

args = parser.parse_args()

exit_code = list_directory(args.directory, args.a, args.one_per_line)
sys.exit(exit_code)

if __name__ == "__main__":
main()
49 changes: 49 additions & 0 deletions implement-shell-tools/wc/wc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import argparse
import sys
import os

def format_output(lines, words, bytes_, label, options):
output = ""
if not (options.l or options.w or options.c):
output += f"{lines:8}{words:8}{bytes_:8}"
else:
if options.l:
output += f"{lines:8}"
if options.w:
output += f"{words:8}"
if options.c:
output += f"{bytes_:8}"
return f"{output} {label}"

def main():
parser = argparse.ArgumentParser(description="Count lines, words, and bytes in files (like wc)")
parser.add_argument("-l", action="store_true", help="count lines")
parser.add_argument("-w", action="store_true", help="count words")
parser.add_argument("-c", action="store_true", help="count bytes")
parser.add_argument("files", nargs="+", help="files to read")
options = parser.parse_args()

total_lines = total_words = total_bytes = 0

for file_path in options.files:
try:
with open(file_path, "r", encoding="utf-8") as f:
data = f.read()

lines = data.count("\n")
words = len(data.split())
bytes_ = len(data.encode("utf-8"))

total_lines += lines
total_words += words
total_bytes += bytes_

print(format_output(lines, words, bytes_, os.path.basename(file_path), options))
except Exception as e:
print(f"Error reading {file_path}: {e}", file=sys.stderr)

if len(options.files) > 1:
print(format_output(total_lines, total_words, total_bytes, "total", options))

if __name__ == "__main__":
main()