From d341d5c022a59e1cbccdcee964133914d0fee6de Mon Sep 17 00:00:00 2001 From: Emilianouz <135679131+Emilianouz@users.noreply.github.com> Date: Fri, 5 Dec 2025 18:37:56 +0000 Subject: [PATCH 1/4] Implementing shell tools: cat, ls, and wc. in Python. --- implement-shell-tools/cat/cat-python.py | 42 ++++++++++++++++ implement-shell-tools/ls/ls-python.py | 33 +++++++++++++ implement-shell-tools/wc/wc-python.py | 66 +++++++++++++++++++++++++ 3 files changed, 141 insertions(+) create mode 100644 implement-shell-tools/cat/cat-python.py create mode 100644 implement-shell-tools/ls/ls-python.py create mode 100644 implement-shell-tools/wc/wc-python.py diff --git a/implement-shell-tools/cat/cat-python.py b/implement-shell-tools/cat/cat-python.py new file mode 100644 index 000000000..7d0edbf3f --- /dev/null +++ b/implement-shell-tools/cat/cat-python.py @@ -0,0 +1,42 @@ +import sys + +def cat_file(filename, flag): + try: + with open(filename, 'r') as file: + if not flag: + for line in file: + print(line, end="") + + elif flag == "-n": + for index, line in enumerate(file, start=1): + print(f"{index:6}\t{line}", end="") + + elif flag == "-b": + line_number = 1 + for line in file: + if line.strip() == "": + print(line, end="") + else: + print(f"{line_number:6}\t{line}", end="") + line_number += 1 + + except FileNotFoundError: + print(f"cat: {filename}: No such file or directory", file=sys.stderr) + +def main(): + args = sys.argv[1:] + + flag = False + + if "-n" in args: + flag = "-n" + args.remove("-n") + elif "-b" in args: + flag = "-b" + args.remove("-b") + + for filename in args: + cat_file(filename, flag) + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/implement-shell-tools/ls/ls-python.py b/implement-shell-tools/ls/ls-python.py new file mode 100644 index 000000000..8b7e2a7bb --- /dev/null +++ b/implement-shell-tools/ls/ls-python.py @@ -0,0 +1,33 @@ +import sys +import os + +def main(): + args = sys.argv[1:] + + path = "." + one_per_line = False + show_hidden = False + + for arg in args: + if arg == "-a": + show_hidden = True + elif arg == "-1": + one_per_line = True + elif not arg.startswith("-"): + path = arg + + entries = os.listdir(path) + + entries.sort() + + if not show_hidden: + entries = [f for f in entries if not f.startswith(".")] + + if one_per_line: + for entry in entries: + print(entry) + else: + print(" ".join(entries)) + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/implement-shell-tools/wc/wc-python.py b/implement-shell-tools/wc/wc-python.py new file mode 100644 index 000000000..8ad2021e5 --- /dev/null +++ b/implement-shell-tools/wc/wc-python.py @@ -0,0 +1,66 @@ +import sys + +def count_file(filename): + + with open(filename, 'r') as file: + content = file.read() + + lines = len(content.splitlines()) + words = len(content.split()) + chars = len(content) + + return (lines, words, chars) + + +def format_output(lines, words, chars, filename, show_l, show_w, show_c): + parts = [] + + if show_l: + parts.append(f"{lines:8}") + if show_w: + parts.append(f"{words:8}") + if show_c: + parts.append(f"{chars:8}") + + parts.append(filename) + + return " ".join(parts) + +def main(): + args = sys.argv[1:] + + l = w = c = False + files = [] + + for arg in args: + if arg == "-l": + l = True + elif arg == "-w": + w = True + elif arg == "-c": + c = True + elif not arg.startswith("-"): + files.append(arg) + + if not (l or w or c): + l = w = c = True + + total_lines = total_words = total_chars = 0 + processed_files = 0 + + for filename in files: + result = count_file(filename) + if result: + lines, words, chars = result + print(format_output(lines, words, chars, filename, l, w, c)) + + total_lines += lines + total_words += words + total_chars += chars + processed_files += 1 + + if processed_files > 1: + print(format_output(total_lines, total_words, total_chars, "total", l, w, c)) + +if __name__ == "__main__": + main() \ No newline at end of file From 2d8a282f37ef76be069caff6c05bcfe1b869d81a Mon Sep 17 00:00:00 2001 From: Emiliano Uruena Date: Mon, 16 Feb 2026 10:13:50 +0000 Subject: [PATCH 2/4] Refactor cat-python.py to use argparse for arguments Add argparse for basic flag parsing and automatic help support --- implement-shell-tools/cat/cat-python.py | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/implement-shell-tools/cat/cat-python.py b/implement-shell-tools/cat/cat-python.py index 7d0edbf3f..fe8e582d6 100644 --- a/implement-shell-tools/cat/cat-python.py +++ b/implement-shell-tools/cat/cat-python.py @@ -1,4 +1,5 @@ import sys +import argparse def cat_file(filename, flag): try: @@ -24,19 +25,25 @@ def cat_file(filename, flag): print(f"cat: {filename}: No such file or directory", file=sys.stderr) def main(): - args = sys.argv[1:] + parser = argparse.ArgumentParser(description="Simple cat clone") - flag = False - - if "-n" in args: + parser.add_argument("filenames", nargs="+", + help="Files to display") + parser.add_argument("-n", action="store_true", + help="Number all output lines") + parser.add_argument("-b", action="store_true", + help="Number non-blank output lines") + + args = parser.parse_args() + + flag = False + if args.n: flag = "-n" - args.remove("-n") - elif "-b" in args: + elif args.b: flag = "-b" - args.remove("-b") - for filename in args: + for filename in args.filenames: cat_file(filename, flag) if __name__ == "__main__": - main() \ No newline at end of file + main() From f792b2049fff28504326d58424dc4e1a3399d82e Mon Sep 17 00:00:00 2001 From: Emiliano Uruena Date: Mon, 16 Feb 2026 13:22:03 +0000 Subject: [PATCH 3/4] Replace sys.argv with argparse in ls-python.py Refactor ls command to use argparse for argument parsing. --- implement-shell-tools/ls/ls-python.py | 29 +++++++++++++-------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/implement-shell-tools/ls/ls-python.py b/implement-shell-tools/ls/ls-python.py index 8b7e2a7bb..3293e565d 100644 --- a/implement-shell-tools/ls/ls-python.py +++ b/implement-shell-tools/ls/ls-python.py @@ -1,20 +1,19 @@ -import sys +import argparse import os def main(): - args = sys.argv[1:] - - path = "." - one_per_line = False - show_hidden = False - - for arg in args: - if arg == "-a": - show_hidden = True - elif arg == "-1": - one_per_line = True - elif not arg.startswith("-"): - path = arg + parser = argparse.ArgumentParser(description=" ls in Python") + + parser.add_argument("path", nargs="?", default=".", help="Directory to list") + parser.add_argument("-a", action="store_true", help="Show hidden files") + parser.add_argument("-1", dest="one_per_line", action="store_true", + help="List one file per line") + + args = parser.parse_args() + + path = args.path + show_hidden = args.a + one_per_line = args.one_per_line entries = os.listdir(path) @@ -30,4 +29,4 @@ def main(): print(" ".join(entries)) if __name__ == "__main__": - main() \ No newline at end of file + main() From 77f35d0e0e5a0474d5a6aa91be2d77dc76467f16 Mon Sep 17 00:00:00 2001 From: Emiliano Uruena Date: Mon, 16 Feb 2026 13:25:48 +0000 Subject: [PATCH 4/4] Refactor argument parsing with argparse Refactor command-line argument parsing to use argparse for better handling of options and file inputs. --- implement-shell-tools/wc/wc-python.py | 31 +++++++++++++-------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/implement-shell-tools/wc/wc-python.py b/implement-shell-tools/wc/wc-python.py index 8ad2021e5..b99c23049 100644 --- a/implement-shell-tools/wc/wc-python.py +++ b/implement-shell-tools/wc/wc-python.py @@ -1,4 +1,4 @@ -import sys +import argparse def count_file(filename): @@ -27,20 +27,19 @@ def format_output(lines, words, chars, filename, show_l, show_w, show_c): return " ".join(parts) def main(): - args = sys.argv[1:] - - l = w = c = False - files = [] - - for arg in args: - if arg == "-l": - l = True - elif arg == "-w": - w = True - elif arg == "-c": - c = True - elif not arg.startswith("-"): - files.append(arg) + parser = argparse.ArgumentParser(description="wc imlementation in Python") + + parser.add_argument("files", nargs="+", help="Files to process") + parser.add_argument("-l", action="store_true", help="Show line count") + parser.add_argument("-w", action="store_true", help="Show word count") + parser.add_argument("-c", action="store_true", help="Show character count") + + args = parser.parse_args() + + l = args.l + w = args.w + c = args.c + files = args.files if not (l or w or c): l = w = c = True @@ -63,4 +62,4 @@ def main(): print(format_output(total_lines, total_words, total_chars, "total", l, w, c)) if __name__ == "__main__": - main() \ No newline at end of file + main()