From 3100694af36400a9a66520ec68eef63243fb1aea Mon Sep 17 00:00:00 2001 From: TzeMingHo Date: Tue, 31 Mar 2026 12:47:49 +0100 Subject: [PATCH 1/8] gitignore .venv --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 3c3629e64..3e5cc695e 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ node_modules +.venv/ \ No newline at end of file From cff00041f03c863e916ee57f690685276382a4ac Mon Sep 17 00:00:00 2001 From: TzeMingHo Date: Tue, 31 Mar 2026 14:45:48 +0100 Subject: [PATCH 2/8] completed cat logic in python --- implement-shell-tools/cat/custom_cat.py | 30 +++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 implement-shell-tools/cat/custom_cat.py diff --git a/implement-shell-tools/cat/custom_cat.py b/implement-shell-tools/cat/custom_cat.py new file mode 100644 index 000000000..29220665c --- /dev/null +++ b/implement-shell-tools/cat/custom_cat.py @@ -0,0 +1,30 @@ +import argparse + +parser = argparse.ArgumentParser( + prog="custom cat in python", + description="trying to match behaviour in actual cat" +) + +parser.add_argument("-b", "--non_blank", action="store_true", help="add number at the beginning of non blank line") +parser.add_argument("-n", "--number", action="store_true", help="add number at the beginning of each line") +parser.add_argument("file_path", nargs="+", help="file path to process") + +args = parser.parse_args() + +count = 1 + +for path in args.file_path: + with open(path, "r") as file: + context = file.read().rstrip().split("\n") + for line in context: + if (args.non_blank): + if (len(line) != 0): + print(f'{str(count).rjust(6, " ")} {line}') + count += 1 + else: + print(line) + elif (args.number): + print(f'{str(count).rjust(6, " ")} {line}') + count += 1 + else: + print(line) \ No newline at end of file From f8cd2064b36805d93b55bbf0b45cca05418af982 Mon Sep 17 00:00:00 2001 From: TzeMingHo Date: Tue, 31 Mar 2026 18:30:27 +0100 Subject: [PATCH 3/8] added standard output of ls --- implement-shell-tools/ls/custom_ls.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 implement-shell-tools/ls/custom_ls.py diff --git a/implement-shell-tools/ls/custom_ls.py b/implement-shell-tools/ls/custom_ls.py new file mode 100644 index 000000000..68a32bfcb --- /dev/null +++ b/implement-shell-tools/ls/custom_ls.py @@ -0,0 +1,21 @@ +import argparse +import os +import re + +parser = argparse.ArgumentParser( + prog="custom ls in python", + description="trying to match behaviour as the actual ls" +) + +parser.add_argument("-a", "--show_hidden", help="show hidden files") +parser.add_argument("path", help="directory path to process", nargs="?", default=".") + +args = parser.parse_args() + +files_array = os.listdir(args.path) + +if (not args.show_hidden): + filtered_list = [file for file in files_array if re.match(r"^(?!\.)", file)] + sorted_file_list = sorted(filtered_list, key=lambda file_name: file_name.lower()) + formatted_list = [f"\033[1;34m{file}\033[0m" if os.path.isdir(os.path.join(args.path, file)) else file for file in sorted_file_list] + print(" ".join(formatted_list)) From 129b9d7e95ef65855c5257f37fa4c459d8c27cae Mon Sep 17 00:00:00 2001 From: TzeMingHo Date: Wed, 1 Apr 2026 14:08:56 +0100 Subject: [PATCH 4/8] finished custom ls logic but it can be improved --- implement-shell-tools/ls/custom_ls.py | 30 ++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/implement-shell-tools/ls/custom_ls.py b/implement-shell-tools/ls/custom_ls.py index 68a32bfcb..301227f3b 100644 --- a/implement-shell-tools/ls/custom_ls.py +++ b/implement-shell-tools/ls/custom_ls.py @@ -2,20 +2,40 @@ import os import re +def sort_list(file_list): + return sorted(file_list, key=lambda file_name: re.sub(r"^\.", "", file_name).lower()) + +def format_list(file_list): + return [f"\033[1;34m{file}\033[0m" if os.path.isdir(os.path.join(args.path, file)) else file for file in file_list] + parser = argparse.ArgumentParser( prog="custom ls in python", description="trying to match behaviour as the actual ls" ) -parser.add_argument("-a", "--show_hidden", help="show hidden files") +parser.add_argument("-a", "--show_hidden", action="store_true", help="show hidden files") +parser.add_argument("-1", "--one_item", action="store_true", help="show one item per one line") parser.add_argument("path", help="directory path to process", nargs="?", default=".") args = parser.parse_args() files_array = os.listdir(args.path) +sorted_files_array = sort_list(files_array) + if (not args.show_hidden): - filtered_list = [file for file in files_array if re.match(r"^(?!\.)", file)] - sorted_file_list = sorted(filtered_list, key=lambda file_name: file_name.lower()) - formatted_list = [f"\033[1;34m{file}\033[0m" if os.path.isdir(os.path.join(args.path, file)) else file for file in sorted_file_list] - print(" ".join(formatted_list)) + filtered_list = [file for file in sorted_files_array if re.match(r"^(?!\.)", file)] + formatted_list = format_list(filtered_list) + if (args.one_item): + for item in formatted_list: + print(item) + else: + print(" ".join(formatted_list)) +else: + sorted_hidden_list = [".", "..", *sorted_files_array] + formatted_hidden_list = format_list(sorted_hidden_list) + if (args.one_item): + for item in formatted_hidden_list: + print(item) + else: + print(" ".join(formatted_hidden_list)) \ No newline at end of file From ded994cafb06c37ffc0e1977b6591b9577a8d617 Mon Sep 17 00:00:00 2001 From: TzeMingHo Date: Thu, 2 Apr 2026 12:34:07 +0100 Subject: [PATCH 5/8] cleaner logic for ls --- implement-shell-tools/ls/custom_ls.py | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/implement-shell-tools/ls/custom_ls.py b/implement-shell-tools/ls/custom_ls.py index 301227f3b..8d0d77a1a 100644 --- a/implement-shell-tools/ls/custom_ls.py +++ b/implement-shell-tools/ls/custom_ls.py @@ -23,19 +23,10 @@ def format_list(file_list): sorted_files_array = sort_list(files_array) -if (not args.show_hidden): - filtered_list = [file for file in sorted_files_array if re.match(r"^(?!\.)", file)] - formatted_list = format_list(filtered_list) - if (args.one_item): - for item in formatted_list: - print(item) - else: - print(" ".join(formatted_list)) -else: - sorted_hidden_list = [".", "..", *sorted_files_array] - formatted_hidden_list = format_list(sorted_hidden_list) - if (args.one_item): - for item in formatted_hidden_list: - print(item) - else: - print(" ".join(formatted_hidden_list)) \ No newline at end of file +hidden_switched_list = [".", "..", *sorted_files_array] if args.show_hidden else [file for file in sorted_files_array if re.match(r"^(?!\.)", file)] + +formatted_list = format_list(hidden_switched_list) + +separator = "\n" if args.one_item else " " + +print(separator.join(formatted_list)) From 11e82325e71b75e0360602d3086290a7a5ea0815 Mon Sep 17 00:00:00 2001 From: TzeMingHo Date: Thu, 2 Apr 2026 14:39:14 +0100 Subject: [PATCH 6/8] working on wc flags --- implement-shell-tools/wc/custom_wc.py | 50 +++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 implement-shell-tools/wc/custom_wc.py diff --git a/implement-shell-tools/wc/custom_wc.py b/implement-shell-tools/wc/custom_wc.py new file mode 100644 index 000000000..ebd71b414 --- /dev/null +++ b/implement-shell-tools/wc/custom_wc.py @@ -0,0 +1,50 @@ +import argparse +import re + +def format_number(number_array): + return [str(number).rjust(4) for number in number_array] + +parser = argparse.ArgumentParser( + prog="custom wc in python", + description="trying to match behaviour in the actual wc" +) + +parser.add_argument("-l", "--lines", action="store_true", help="count how many lines") +parser.add_argument("-w", "--words", action="store_true", help="count how many words") +parser.add_argument("-c", "--characters", action="store_true", help="count how many characters") +parser.add_argument("path", nargs="+", help="path to process") + +args = parser.parse_args() + +files_array = args.path + +total_lines = 0 +total_words = 0 +total_characters = 0 + +numbers_row_array = [] + +for file_path in files_array: + with open(file_path) as file: + context = file.read() + lines = len(context.split("\n")) - 1 + words = len(re.findall(r"\S+", context)) + characters = len(context) + + if (args.lines): + numbers_row_array.append(lines) + if (args.words): + numbers_row_array.append(words) + if (args.characters): + numbers_row_array.append(characters) + + if (len(numbers_row_array) > 0): + print(numbers_row_array) + else: + print(lines, words, characters, file_path) + total_lines += lines + total_words += words + total_characters += characters + +if (len(files_array) > 1): + print(total_lines, total_words, total_characters, 'total') \ No newline at end of file From 3d0b1bf9d24a817bd45f754ce261e58040288cdc Mon Sep 17 00:00:00 2001 From: TzeMingHo Date: Thu, 2 Apr 2026 17:16:46 +0100 Subject: [PATCH 7/8] completed logic for wc in python --- implement-shell-tools/wc/custom_wc.py | 28 +++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/implement-shell-tools/wc/custom_wc.py b/implement-shell-tools/wc/custom_wc.py index ebd71b414..a826e7925 100644 --- a/implement-shell-tools/wc/custom_wc.py +++ b/implement-shell-tools/wc/custom_wc.py @@ -2,7 +2,9 @@ import re def format_number(number_array): - return [str(number).rjust(4) for number in number_array] + space_array = [3, 4, 4] + result = map(lambda number, space: str(number).rjust(space), number_array, space_array) + return "".join(list(result)) parser = argparse.ArgumentParser( prog="custom wc in python", @@ -22,7 +24,7 @@ def format_number(number_array): total_words = 0 total_characters = 0 -numbers_row_array = [] +total_numbers_row_array = [] for file_path in files_array: with open(file_path) as file: @@ -31,20 +33,34 @@ def format_number(number_array): words = len(re.findall(r"\S+", context)) characters = len(context) + numbers_row_array = [] if (args.lines): numbers_row_array.append(lines) if (args.words): numbers_row_array.append(words) if (args.characters): numbers_row_array.append(characters) + + if (len(numbers_row_array) == 1 and len(files_array) == 1): + print(f'{numbers_row_array[0]} {file_path}') - if (len(numbers_row_array) > 0): - print(numbers_row_array) + elif (len(numbers_row_array) > 0): + print(f'{format_number(numbers_row_array)} {file_path}') else: - print(lines, words, characters, file_path) + print(format_number([lines, words, characters]), file_path) + total_lines += lines total_words += words total_characters += characters if (len(files_array) > 1): - print(total_lines, total_words, total_characters, 'total') \ No newline at end of file + if (args.lines): + total_numbers_row_array.append(total_lines) + if (args.words): + total_numbers_row_array.append(total_words) + if (args.characters): + total_numbers_row_array.append(total_characters) + if (len(total_numbers_row_array) > 0): + print(f'{format_number(total_numbers_row_array)} total') + else: + print(format_number([total_lines, total_words, total_characters]), 'total') \ No newline at end of file From 605f45de65614dd184360d54a476b08de09f7937 Mon Sep 17 00:00:00 2001 From: TzeMingHo Date: Thu, 2 Apr 2026 17:20:38 +0100 Subject: [PATCH 8/8] restored .gitignore --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index 3e5cc695e..3c3629e64 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1 @@ node_modules -.venv/ \ No newline at end of file