From 60d67015ebe7bcdb4ad1cce1f5f64502440314a4 Mon Sep 17 00:00:00 2001 From: HilolaRustamova Date: Tue, 9 Jun 2026 10:43:37 +0100 Subject: [PATCH 1/7] created files for shell tools with python --- .gitignore | 1 + implement-shell-tools/cat/mycat.py | 27 +++++++++++++++++++++++++++ implement-shell-tools/ls/my-ls.py | 0 implement-shell-tools/wc/my-wc.py | 0 4 files changed, 28 insertions(+) create mode 100644 implement-shell-tools/cat/mycat.py create mode 100644 implement-shell-tools/ls/my-ls.py create mode 100644 implement-shell-tools/wc/my-wc.py diff --git a/.gitignore b/.gitignore index 3c3629e64..8aa876ab0 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ node_modules +venv \ No newline at end of file diff --git a/implement-shell-tools/cat/mycat.py b/implement-shell-tools/cat/mycat.py new file mode 100644 index 000000000..52405a9b3 --- /dev/null +++ b/implement-shell-tools/cat/mycat.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 + +import sys +import glob +import os + +def expand_paths(paths): + """Expand glob patterns and return sorted unique file list.""" + files = [] + for p in paths: + matches = glob.glob(p) + if matches: + files.extend(matches) + else: + files.append(p) # keep as-is (will error later if missing) + return sorted(files) + +def read_lines(file): + with open(file, "r", encoding="utf-8") as f: + return f.readlines() + +def print_lines(files, number_lines==False, number_nonempty=False): + line_no = 1 + for file in files: + + + \ No newline at end of file diff --git a/implement-shell-tools/ls/my-ls.py b/implement-shell-tools/ls/my-ls.py new file mode 100644 index 000000000..e69de29bb diff --git a/implement-shell-tools/wc/my-wc.py b/implement-shell-tools/wc/my-wc.py new file mode 100644 index 000000000..e69de29bb From aee68b755754900596087c3f43ee2d267de44f81 Mon Sep 17 00:00:00 2001 From: HilolaRustamova Date: Wed, 10 Jun 2026 13:01:51 +0100 Subject: [PATCH 2/7] implementation of cat with python --- implement-shell-tools/.gitignore | 1 + implement-shell-tools/cat/mycat.py | 57 +++++++++++++++++++++++++++--- 2 files changed, 54 insertions(+), 4 deletions(-) create mode 100644 implement-shell-tools/.gitignore diff --git a/implement-shell-tools/.gitignore b/implement-shell-tools/.gitignore new file mode 100644 index 000000000..0cafc1cde --- /dev/null +++ b/implement-shell-tools/.gitignore @@ -0,0 +1 @@ +.venv/ \ No newline at end of file diff --git a/implement-shell-tools/cat/mycat.py b/implement-shell-tools/cat/mycat.py index 52405a9b3..a8511d944 100644 --- a/implement-shell-tools/cat/mycat.py +++ b/implement-shell-tools/cat/mycat.py @@ -13,15 +13,64 @@ def expand_paths(paths): files.extend(matches) else: files.append(p) # keep as-is (will error later if missing) - return sorted(files) + return sorted(files) def read_lines(file): with open(file, "r", encoding="utf-8") as f: return f.readlines() -def print_lines(files, number_lines==False, number_nonempty=False): +def print_lines(files, number_all=False, number_nonempty=False): line_no = 1 for file in files: - + try: + lines = read_lines(file) + except FileNotFoundError: + print(f"cat: {file}: No such file or directory", file=sys.stderr) + continue - \ No newline at end of file + for line in lines: + is_empty = (line.strip() == "") + + if number_nonempty: + if not is_empty: + prefix = f"{line_no:6}\t" + line_no += 1 + else: + prefix = "" + elif number_all: + prefix = f"{line_no:6}\t" + line_no += 1 + else: + prefix = "" + + # avoid double newlines: line already includes '\n' + sys.stdout.write(prefix + line) + + +def main(): + args = sys.argv[1:] + + if not args: + print("Usage: cat [-n|-b] file...", file=sys.stderr) + sys.exit(1) + + number_all = False + number_nonempty = False + paths = [] + + for a in args: + if a == "-n": + number_all = True + elif a == "-b": + number_nonempty = True + number_all = False #-b overrides -n + else: + paths.append(a) + + files = expand_paths(paths) + print_lines(files, number_all,number_nonempty) + + +if __name__ == "__main__": + main() + \ No newline at end of file From 80ca854f1b93ff9b99631f45eaa4a5b44d8676ca Mon Sep 17 00:00:00 2001 From: HilolaRustamova Date: Wed, 10 Jun 2026 14:07:21 +0100 Subject: [PATCH 3/7] implementation of ls with python --- implement-shell-tools/cat/mycat.py | 2 +- implement-shell-tools/ls/my-ls.py | 48 ++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/implement-shell-tools/cat/mycat.py b/implement-shell-tools/cat/mycat.py index a8511d944..3badd3960 100644 --- a/implement-shell-tools/cat/mycat.py +++ b/implement-shell-tools/cat/mycat.py @@ -2,7 +2,7 @@ import sys import glob -import os + def expand_paths(paths): """Expand glob patterns and return sorted unique file list.""" diff --git a/implement-shell-tools/ls/my-ls.py b/implement-shell-tools/ls/my-ls.py index e69de29bb..a1e798a36 100644 --- a/implement-shell-tools/ls/my-ls.py +++ b/implement-shell-tools/ls/my-ls.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 + +import sys +import os + +def list_dir(path, show_all=False, one_per_line = False): + try: + entries = os.listdir(path) + except FileNotFoundError: + print(f"ls: cannot access '{path}': No such file or directory", file=sys.stderr) + return + + entries = sorted(entries) + + if show_all: + normal = sorted([e for e in entries if not e.startswith('.')]) + hidden = sorted([e for e in entries if e.startswith('.')]) + + entries = [".", ".."] + normal + hidden + else: + entries = sorted([e for e in entries if not e.startswith('.')]) + + for entry in entries: + print(entry) + +def main(): + args = sys.argv[1:] + + show_all = False + one_per_line = False + paths = [] + + for a in args: + if a == "-a": + show_all = True + elif a == "-1": + one_per_line = True + else: + paths.append(a) + + if not paths: + paths = ["."] + + for path in paths: + list_dir(path, show_all, one_per_line) + +if __name__ == "__main__": + main() \ No newline at end of file From 1e3fc255c7aeaf156ac4155ea99678d44d894c16 Mon Sep 17 00:00:00 2001 From: HilolaRustamova Date: Wed, 10 Jun 2026 14:54:56 +0100 Subject: [PATCH 4/7] implementation of wc with python --- implement-shell-tools/wc/my-wc.py | 104 ++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/implement-shell-tools/wc/my-wc.py b/implement-shell-tools/wc/my-wc.py index e69de29bb..1a43a36c8 100644 --- a/implement-shell-tools/wc/my-wc.py +++ b/implement-shell-tools/wc/my-wc.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python3 + +import sys +import glob + +def count_file(path): + with open(path, "rb") as f: + content = f.read() + + byte_count = len(content) + text = content.decode("utf-8", errors="ignore") + + line_count = text.count("\n") + word_count = len(text.split()) + + return line_count, word_count, byte_count + +def expand(paths): + files = [] + for p in paths: + matches = glob.glob(p) + if matches: + files.extend(matches) + else: + files.append(p) + return files + +def main(): + args = sys.argv[1:] + + show_l = False + show_w = False + show_c = False + + paths = [] + + + # parse args + for a in args: + if a == "-l": + show_l = True + elif a == "-w": + show_w = True + elif a == "-c": + show_c = True + else: + paths.append(a) + + # default: show all + if not (show_l or show_w or show_c): + show_l = show_w = show_c = True + + files = expand(paths) + + total_l = 0 + total_w = 0 + total_c = 0 + + results = [] + + for file in files: + try: + l, w, c = count_file(file) + except FileNotFoundError: + print(f"wc: {file}: No such file or directory", file=sys.stderr) + continue + + total_l += l + total_w += w + total_c += c + + results.append((l,w,c, file)) + + # print per-file results (GNU-aligned formatting) + for l, w, c, file in results: + + parts = [] + if show_l: + parts.append(f"{l:3}") + if show_w: + parts.append(f"{w:4}") + if show_c: + parts.append(f"{c:4}") + + + print("".join(parts) + " " + file) + + # print total if multiple files + if len(results) > 1: + parts = [] + + if show_l: + parts.append(f"{total_l:3}") + if show_w: + parts.append(f"{total_w:4}") + if show_c: + parts.append(f"{total_c:4}") + + + print("".join(parts) + " total") + + +if __name__ == "__main__": + main() \ No newline at end of file From efadbb0babf4a9959dbbe62ab900eb3b2488be14 Mon Sep 17 00:00:00 2001 From: HilolaRustamova Date: Thu, 11 Jun 2026 11:13:16 +0100 Subject: [PATCH 5/7] error handling corrected, structure is changed, indentation fixed --- implement-shell-tools/cat/mycat.py | 67 ++++++++++++++++++------------ 1 file changed, 40 insertions(+), 27 deletions(-) diff --git a/implement-shell-tools/cat/mycat.py b/implement-shell-tools/cat/mycat.py index 3badd3960..d3546075f 100644 --- a/implement-shell-tools/cat/mycat.py +++ b/implement-shell-tools/cat/mycat.py @@ -3,7 +3,40 @@ import sys import glob +def main(): + args = sys.argv[1:] + + if not args: + print("Usage: cat [-n|-b] file...", file=sys.stderr) + sys.exit(1) + + number_all = False + number_nonempty = False + paths = [] + + for a in args: + if a == "-n": + number_all = True + elif a == "-b": + number_nonempty = True + else: + paths.append(a) + + if number_nonempty: + number_all = False + + files = expand_paths(paths) + + had_error = print_lines( + files, + number_all=number_all, + number_nonempty=number_nonempty, + ) + + if had_error: + sys.exit(1) + def expand_paths(paths): """Expand glob patterns and return sorted unique file list.""" files = [] @@ -16,16 +49,18 @@ def expand_paths(paths): return sorted(files) def read_lines(file): - with open(file, "r", encoding="utf-8") as f: - return f.readlines() + with open(file, "r", encoding="utf-8") as f: + return f.readlines() def print_lines(files, number_all=False, number_nonempty=False): + had_error = False line_no = 1 for file in files: try: lines = read_lines(file) except FileNotFoundError: print(f"cat: {file}: No such file or directory", file=sys.stderr) + had_error = True continue for line in lines: @@ -46,31 +81,9 @@ def print_lines(files, number_all=False, number_nonempty=False): # avoid double newlines: line already includes '\n' sys.stdout.write(prefix + line) + return had_error -def main(): - args = sys.argv[1:] - - if not args: - print("Usage: cat [-n|-b] file...", file=sys.stderr) - sys.exit(1) - - number_all = False - number_nonempty = False - paths = [] - - for a in args: - if a == "-n": - number_all = True - elif a == "-b": - number_nonempty = True - number_all = False #-b overrides -n - else: - paths.append(a) - - files = expand_paths(paths) - print_lines(files, number_all,number_nonempty) - - if __name__ == "__main__": - main() + main() + \ No newline at end of file From ad6883f945cd40ec3bdef4f49119b99ec0cd9177 Mon Sep 17 00:00:00 2001 From: HilolaRustamova Date: Thu, 11 Jun 2026 11:30:21 +0100 Subject: [PATCH 6/7] corrected error handling issue and moved the main up. --- implement-shell-tools/ls/my-ls.py | 49 +++++++++++++++++++------------ 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/implement-shell-tools/ls/my-ls.py b/implement-shell-tools/ls/my-ls.py index a1e798a36..be597a33f 100644 --- a/implement-shell-tools/ls/my-ls.py +++ b/implement-shell-tools/ls/my-ls.py @@ -3,25 +3,7 @@ import sys import os -def list_dir(path, show_all=False, one_per_line = False): - try: - entries = os.listdir(path) - except FileNotFoundError: - print(f"ls: cannot access '{path}': No such file or directory", file=sys.stderr) - return - - entries = sorted(entries) - - if show_all: - normal = sorted([e for e in entries if not e.startswith('.')]) - hidden = sorted([e for e in entries if e.startswith('.')]) - - entries = [".", ".."] + normal + hidden - else: - entries = sorted([e for e in entries if not e.startswith('.')]) - for entry in entries: - print(entry) def main(): args = sys.argv[1:] @@ -41,8 +23,37 @@ def main(): if not paths: paths = ["."] + had_error = False + for path in paths: - list_dir(path, show_all, one_per_line) + if list_dir(path, show_all, one_per_line): + had_error = True + + if had_error: + sys.exit(1) + + +def list_dir(path, show_all=False, one_per_line = False): + try: + entries = os.listdir(path) + except FileNotFoundError: + print(f"ls: cannot access '{path}': No such file or directory", file=sys.stderr) + return True + + entries = sorted(entries) + + if show_all: + normal = sorted([e for e in entries if not e.startswith('.')]) + hidden = sorted([e for e in entries if e.startswith('.')]) + + entries = [".", ".."] + normal + hidden + else: + entries = sorted([e for e in entries if not e.startswith('.')]) + + for entry in entries: + print(entry) + + if __name__ == "__main__": main() \ No newline at end of file From db7c86a9e48763658a670e46adef096888446daf Mon Sep 17 00:00:00 2001 From: HilolaRustamova Date: Thu, 11 Jun 2026 11:50:27 +0100 Subject: [PATCH 7/7] small changes --- implement-shell-tools/ls/my-ls.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/implement-shell-tools/ls/my-ls.py b/implement-shell-tools/ls/my-ls.py index be597a33f..748a6d7b6 100644 --- a/implement-shell-tools/ls/my-ls.py +++ b/implement-shell-tools/ls/my-ls.py @@ -26,18 +26,24 @@ def main(): had_error = False for path in paths: - if list_dir(path, show_all, one_per_line): + if list_dir( + path, + show_all=show_all, + one_per_line=one_per_line, + ): had_error = True if had_error: sys.exit(1) -def list_dir(path, show_all=False, one_per_line = False): +def list_dir(path, show_all=False, one_per_line=False): try: entries = os.listdir(path) except FileNotFoundError: - print(f"ls: cannot access '{path}': No such file or directory", file=sys.stderr) + print(f"ls: cannot access '{path}': No such file or directory", + file=sys.stderr, + ) return True entries = sorted(entries) @@ -53,7 +59,7 @@ def list_dir(path, show_all=False, one_per_line = False): for entry in entries: print(entry) - + return False if __name__ == "__main__": main() \ No newline at end of file