From 46752468729ff31f38955b1c26b114838ac3c534 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Mon, 1 Dec 2025 13:24:30 +0000 Subject: [PATCH 01/69] create cat.py file to write our implementation on it --- implement-shell-tools/cat/cat.py | 52 ++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 implement-shell-tools/cat/cat.py diff --git a/implement-shell-tools/cat/cat.py b/implement-shell-tools/cat/cat.py new file mode 100644 index 00000000..871d4e95 --- /dev/null +++ b/implement-shell-tools/cat/cat.py @@ -0,0 +1,52 @@ +# import process from "node:process"; +# import {promises as fs} from "node:fs"; +# import {program} from "commander"; + +# program +# .name("display-file-content") +# .description("Output the content of a file to the terminal") +# .argument("", "The file path to process") +# .option("-n", "Number the output lines") +# .option("-b","Number the non-blank output lines") + +# program.parse(); + +# const paths = program.args; + +# const options = program.opts(); + +# let lineNumber = 1; + +# for (const path of paths) { +# const filesContent = await fs.readFile(path, "utf-8"); + +# const lines = filesContent.split("\n"); + +# if (lines[lines.length - 1] === "") { +# lines.pop(); +# } + +# for (let line of lines) { +# if (options.n) { +# process.stdout.write(`${lineNumber} ${line}\n`); +# lineNumber++; +# } else if (options.b) { +# if (line != "") { +# process.stdout.write(`${lineNumber} ${line}\n`); +# lineNumber++; +# } else { +# process.stdout.write("\n"); +# } +# } else { +# process.stdout.write(line + "\n"); +# } +# } +# } + + + + + + + + From 95cfc324f5388c973cab0248fcfc0edac3a3af38 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Mon, 1 Dec 2025 13:27:44 +0000 Subject: [PATCH 02/69] import argparse library --- implement-shell-tools/cat/cat.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/implement-shell-tools/cat/cat.py b/implement-shell-tools/cat/cat.py index 871d4e95..23f0fafb 100644 --- a/implement-shell-tools/cat/cat.py +++ b/implement-shell-tools/cat/cat.py @@ -43,6 +43,10 @@ # } # } +import argparse + + + From 530a234ff19dfcf433e5645becde58eb22ab56a2 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Mon, 1 Dec 2025 13:30:57 +0000 Subject: [PATCH 03/69] define program meta data --- implement-shell-tools/cat/cat.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/implement-shell-tools/cat/cat.py b/implement-shell-tools/cat/cat.py index 23f0fafb..1e6c8b7b 100644 --- a/implement-shell-tools/cat/cat.py +++ b/implement-shell-tools/cat/cat.py @@ -45,6 +45,11 @@ import argparse +parser = argparse.ArgumentParser( + prog="display-file-content", + description="Output the content of a file to the terminal", +) + From 2fc8e5d7d44e72b0d367a5cc3c486c05be949857 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Mon, 1 Dec 2025 13:32:16 +0000 Subject: [PATCH 04/69] define the -n option --- implement-shell-tools/cat/cat.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/implement-shell-tools/cat/cat.py b/implement-shell-tools/cat/cat.py index 1e6c8b7b..bfa7ff19 100644 --- a/implement-shell-tools/cat/cat.py +++ b/implement-shell-tools/cat/cat.py @@ -50,7 +50,7 @@ description="Output the content of a file to the terminal", ) - +parser.add_argument("-n", help="Number the output lines") From 73369ea9014ad6f15f2815a51c701154e820a461 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Mon, 1 Dec 2025 13:32:49 +0000 Subject: [PATCH 05/69] define the -b option/flag --- implement-shell-tools/cat/cat.py | 1 + 1 file changed, 1 insertion(+) diff --git a/implement-shell-tools/cat/cat.py b/implement-shell-tools/cat/cat.py index bfa7ff19..35fde823 100644 --- a/implement-shell-tools/cat/cat.py +++ b/implement-shell-tools/cat/cat.py @@ -51,6 +51,7 @@ ) parser.add_argument("-n", help="Number the output lines") +parser.add_argument("-b", help="Number the non-blank output lines") From 3bb2ce986e0f8182e19e9e7e51a14c43efabfe0f Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Mon, 1 Dec 2025 13:35:33 +0000 Subject: [PATCH 06/69] define the path / file to read from --- implement-shell-tools/cat/cat.py | 1 + 1 file changed, 1 insertion(+) diff --git a/implement-shell-tools/cat/cat.py b/implement-shell-tools/cat/cat.py index 35fde823..587e7a34 100644 --- a/implement-shell-tools/cat/cat.py +++ b/implement-shell-tools/cat/cat.py @@ -52,6 +52,7 @@ parser.add_argument("-n", help="Number the output lines") parser.add_argument("-b", help="Number the non-blank output lines") +parser.add_argument("path", help="The file to read from") From 652c027694e415dbc2c5cbd4fbfa7bda8dc671c4 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Mon, 1 Dec 2025 13:38:06 +0000 Subject: [PATCH 07/69] read the command line argument during runtime --- implement-shell-tools/cat/cat.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/implement-shell-tools/cat/cat.py b/implement-shell-tools/cat/cat.py index 587e7a34..ea26c1a6 100644 --- a/implement-shell-tools/cat/cat.py +++ b/implement-shell-tools/cat/cat.py @@ -54,6 +54,8 @@ parser.add_argument("-b", help="Number the non-blank output lines") parser.add_argument("path", help="The file to read from") +args = parser.parse_args + From 1f95e098ca30304c690ee949e0d9b76dbd69a7e6 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Mon, 1 Dec 2025 13:41:11 +0000 Subject: [PATCH 08/69] open the file/path for reading and laod its content --- implement-shell-tools/cat/cat.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/implement-shell-tools/cat/cat.py b/implement-shell-tools/cat/cat.py index ea26c1a6..f5b7f4e9 100644 --- a/implement-shell-tools/cat/cat.py +++ b/implement-shell-tools/cat/cat.py @@ -56,7 +56,8 @@ args = parser.parse_args - +with open(args.path, "r") as f: + content = f.read() From 9de5129dd88a02cf2f9c9dd3891b5ddfc1cbe0c9 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Mon, 1 Dec 2025 13:47:49 +0000 Subject: [PATCH 09/69] added () to resolve buggy code --- implement-shell-tools/cat/cat.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/implement-shell-tools/cat/cat.py b/implement-shell-tools/cat/cat.py index f5b7f4e9..2ac467bd 100644 --- a/implement-shell-tools/cat/cat.py +++ b/implement-shell-tools/cat/cat.py @@ -54,13 +54,13 @@ parser.add_argument("-b", help="Number the non-blank output lines") parser.add_argument("path", help="The file to read from") -args = parser.parse_args +args = parser.parse_args() with open(args.path, "r") as f: content = f.read() - +print(f) From 42b98a5a7ca5b4264f65ea1c4735565bfc6a7b47 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Mon, 1 Dec 2025 13:53:24 +0000 Subject: [PATCH 10/69] splitting file content by end of line --- implement-shell-tools/cat/cat.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/implement-shell-tools/cat/cat.py b/implement-shell-tools/cat/cat.py index 2ac467bd..0a341577 100644 --- a/implement-shell-tools/cat/cat.py +++ b/implement-shell-tools/cat/cat.py @@ -59,8 +59,9 @@ with open(args.path, "r") as f: content = f.read() + lines = content.split("\n") + -print(f) From f1444f969a96f5a7681d298da163631d4348d6a1 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Mon, 1 Dec 2025 13:59:01 +0000 Subject: [PATCH 11/69] after splitting the file content into lines checking if the last line is blak and if so removes it --- implement-shell-tools/cat/cat.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/implement-shell-tools/cat/cat.py b/implement-shell-tools/cat/cat.py index 0a341577..022555a0 100644 --- a/implement-shell-tools/cat/cat.py +++ b/implement-shell-tools/cat/cat.py @@ -60,6 +60,9 @@ content = f.read() lines = content.split("\n") + if lines[len(lines) - 1] == "": + lines.pop() + From 4da743063cc3271bb3d460fac6bdca132af4ff45 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Mon, 1 Dec 2025 14:14:37 +0000 Subject: [PATCH 12/69] handle -n flag case --- implement-shell-tools/cat/cat.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/implement-shell-tools/cat/cat.py b/implement-shell-tools/cat/cat.py index 022555a0..7c44af2e 100644 --- a/implement-shell-tools/cat/cat.py +++ b/implement-shell-tools/cat/cat.py @@ -56,6 +56,8 @@ args = parser.parse_args() +line_number = 1 + with open(args.path, "r") as f: content = f.read() @@ -63,6 +65,11 @@ if lines[len(lines) - 1] == "": lines.pop() + for line in lines: + if args.n: + print(f"{line_number} ${line}\n") + line_number++ + From 414ebd754d4c77c3d95f2195327df4f1d1a2ba4c Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Mon, 1 Dec 2025 14:18:20 +0000 Subject: [PATCH 13/69] handles the -b option case and it's 2 scenarios --- implement-shell-tools/cat/cat.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/implement-shell-tools/cat/cat.py b/implement-shell-tools/cat/cat.py index 7c44af2e..e5585c09 100644 --- a/implement-shell-tools/cat/cat.py +++ b/implement-shell-tools/cat/cat.py @@ -69,6 +69,14 @@ if args.n: print(f"{line_number} ${line}\n") line_number++ + elif args.b: + if line != "": + print(f"{line_number} ${line}\n") + line_number++ + else: + print("\n") + + From a0daa7677ec44674ae2009ca0585a1e000b1b4a0 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Mon, 1 Dec 2025 14:20:13 +0000 Subject: [PATCH 14/69] if no flag is selected print the content --- implement-shell-tools/cat/cat.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/implement-shell-tools/cat/cat.py b/implement-shell-tools/cat/cat.py index e5585c09..fe06f0f6 100644 --- a/implement-shell-tools/cat/cat.py +++ b/implement-shell-tools/cat/cat.py @@ -75,6 +75,8 @@ line_number++ else: print("\n") + else: + print(f"{line} + \n") From cd5256b933fced200dbf8c03bdec9df21852d615 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Mon, 1 Dec 2025 14:21:48 +0000 Subject: [PATCH 15/69] corrected the increment to follow python syntax --- implement-shell-tools/cat/cat.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/implement-shell-tools/cat/cat.py b/implement-shell-tools/cat/cat.py index fe06f0f6..1cca3537 100644 --- a/implement-shell-tools/cat/cat.py +++ b/implement-shell-tools/cat/cat.py @@ -68,11 +68,11 @@ for line in lines: if args.n: print(f"{line_number} ${line}\n") - line_number++ + line_number += 1 elif args.b: if line != "": print(f"{line_number} ${line}\n") - line_number++ + line_number += 1 else: print("\n") else: From b1bf214244fe3c8383104d802b441158cd35b71f Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Mon, 1 Dec 2025 14:24:03 +0000 Subject: [PATCH 16/69] corrected the logic for when no flag was selected --- implement-shell-tools/cat/cat.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/implement-shell-tools/cat/cat.py b/implement-shell-tools/cat/cat.py index 1cca3537..85aee3a0 100644 --- a/implement-shell-tools/cat/cat.py +++ b/implement-shell-tools/cat/cat.py @@ -76,7 +76,7 @@ else: print("\n") else: - print(f"{line} + \n") + print(f"{line}") From d0bb38791532fa6200c48f5670e25b92901d4277 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Mon, 1 Dec 2025 14:30:34 +0000 Subject: [PATCH 17/69] adding action="store_true" so that the program doesn't expect values for -n & -b options --- implement-shell-tools/cat/cat.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/implement-shell-tools/cat/cat.py b/implement-shell-tools/cat/cat.py index 85aee3a0..88568009 100644 --- a/implement-shell-tools/cat/cat.py +++ b/implement-shell-tools/cat/cat.py @@ -50,8 +50,8 @@ description="Output the content of a file to the terminal", ) -parser.add_argument("-n", help="Number the output lines") -parser.add_argument("-b", help="Number the non-blank output lines") +parser.add_argument("-n", help="Number the output lines", action="store_true") +parser.add_argument("-b", help="Number the non-blank output lines", action="store_true") parser.add_argument("path", help="The file to read from") args = parser.parse_args() From 80e39094f47df162e631b577a18f9ffe6464edfa Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Mon, 1 Dec 2025 14:32:00 +0000 Subject: [PATCH 18/69] corrected code to follow python syntax --- implement-shell-tools/cat/cat.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/implement-shell-tools/cat/cat.py b/implement-shell-tools/cat/cat.py index 88568009..ea0c1684 100644 --- a/implement-shell-tools/cat/cat.py +++ b/implement-shell-tools/cat/cat.py @@ -67,11 +67,11 @@ for line in lines: if args.n: - print(f"{line_number} ${line}\n") + print(f"{line_number} {line}\n") line_number += 1 elif args.b: if line != "": - print(f"{line_number} ${line}\n") + print(f"{line_number} {line}\n") line_number += 1 else: print("\n") From 3ce06c4c23bd98caff185132f3b2f76287f32bd7 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Mon, 1 Dec 2025 15:25:45 +0000 Subject: [PATCH 19/69] correct logic for options to further mimic cat tool behaviour --- implement-shell-tools/cat/cat.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/implement-shell-tools/cat/cat.py b/implement-shell-tools/cat/cat.py index ea0c1684..f2925d5c 100644 --- a/implement-shell-tools/cat/cat.py +++ b/implement-shell-tools/cat/cat.py @@ -67,14 +67,14 @@ for line in lines: if args.n: - print(f"{line_number} {line}\n") + print(f"{line_number} {line}") line_number += 1 elif args.b: if line != "": - print(f"{line_number} {line}\n") + print(f"{line_number} {line}") line_number += 1 else: - print("\n") + print(f"{line}") else: print(f"{line}") From e93d1f96f16171faf39e7b42953ab19f5e6d6c94 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Mon, 1 Dec 2025 15:34:24 +0000 Subject: [PATCH 20/69] corrected logic to handle several files/path arguments --- implement-shell-tools/cat/cat.py | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/implement-shell-tools/cat/cat.py b/implement-shell-tools/cat/cat.py index f2925d5c..6ef85a99 100644 --- a/implement-shell-tools/cat/cat.py +++ b/implement-shell-tools/cat/cat.py @@ -52,31 +52,32 @@ parser.add_argument("-n", help="Number the output lines", action="store_true") parser.add_argument("-b", help="Number the non-blank output lines", action="store_true") -parser.add_argument("path", help="The file to read from") +parser.add_argument("paths", help="The file(s)/path(s) to read from", nargs="+") args = parser.parse_args() line_number = 1 -with open(args.path, "r") as f: - content = f.read() +for path in args.paths: + with open(path, "r") as f: + content = f.read() - lines = content.split("\n") - if lines[len(lines) - 1] == "": - lines.pop() + lines = content.split("\n") + if lines[len(lines) - 1] == "": + lines.pop() - for line in lines: - if args.n: - print(f"{line_number} {line}") - line_number += 1 - elif args.b: - if line != "": + for line in lines: + if args.n: print(f"{line_number} {line}") line_number += 1 + elif args.b: + if line != "": + print(f"{line_number} {line}") + line_number += 1 + else: + print(f"{line}") else: print(f"{line}") - else: - print(f"{line}") From f1b5a238c77a17997905d5459f7095baf75181a2 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Mon, 1 Dec 2025 15:36:16 +0000 Subject: [PATCH 21/69] remove js implementation which used to guide me to do the python implementation --- implement-shell-tools/cat/cat.py | 45 -------------------------------- 1 file changed, 45 deletions(-) diff --git a/implement-shell-tools/cat/cat.py b/implement-shell-tools/cat/cat.py index 6ef85a99..ceaacb1e 100644 --- a/implement-shell-tools/cat/cat.py +++ b/implement-shell-tools/cat/cat.py @@ -1,48 +1,3 @@ -# import process from "node:process"; -# import {promises as fs} from "node:fs"; -# import {program} from "commander"; - -# program -# .name("display-file-content") -# .description("Output the content of a file to the terminal") -# .argument("", "The file path to process") -# .option("-n", "Number the output lines") -# .option("-b","Number the non-blank output lines") - -# program.parse(); - -# const paths = program.args; - -# const options = program.opts(); - -# let lineNumber = 1; - -# for (const path of paths) { -# const filesContent = await fs.readFile(path, "utf-8"); - -# const lines = filesContent.split("\n"); - -# if (lines[lines.length - 1] === "") { -# lines.pop(); -# } - -# for (let line of lines) { -# if (options.n) { -# process.stdout.write(`${lineNumber} ${line}\n`); -# lineNumber++; -# } else if (options.b) { -# if (line != "") { -# process.stdout.write(`${lineNumber} ${line}\n`); -# lineNumber++; -# } else { -# process.stdout.write("\n"); -# } -# } else { -# process.stdout.write(line + "\n"); -# } -# } -# } - import argparse parser = argparse.ArgumentParser( From f3e7e68d6874d01441240e143e8f53ee2a2f0a6e Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Mon, 1 Dec 2025 15:38:39 +0000 Subject: [PATCH 22/69] create ls.py file to implement ls tool in python in it --- implement-shell-tools/ls/ls.py | 45 ++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 implement-shell-tools/ls/ls.py diff --git a/implement-shell-tools/ls/ls.py b/implement-shell-tools/ls/ls.py new file mode 100644 index 00000000..e46897d9 --- /dev/null +++ b/implement-shell-tools/ls/ls.py @@ -0,0 +1,45 @@ +# import process from "node:process"; +# import {promises as fs} from "node:fs"; +# import {program} from "commander"; + +# program +# .name("display-file-content") +# .description("Output the content of a file to the terminal") +# .argument("", "The file path to process") +# .option("-n", "Number the output lines") +# .option("-b","Number the non-blank output lines") + +# program.parse(); + +# const paths = program.args; + +# const options = program.opts(); + +# let lineNumber = 1; + +# for (const path of paths) { +# const filesContent = await fs.readFile(path, "utf-8"); + +# const lines = filesContent.split("\n"); + +# if (lines[lines.length - 1] === "") { +# lines.pop(); +# } + +# for (let line of lines) { +# if (options.n) { +# process.stdout.write(`${lineNumber} ${line}\n`); +# lineNumber++; +# } else if (options.b) { +# if (line != "") { +# process.stdout.write(`${lineNumber} ${line}\n`); +# lineNumber++; +# } else { +# process.stdout.write("\n"); +# } +# } else { +# process.stdout.write(line + "\n"); +# } +# } +# } + From 1cbdfd48c9dc714bf8090fa745d0f480b5a3a2e8 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Mon, 1 Dec 2025 15:39:43 +0000 Subject: [PATCH 23/69] add ls implementation in js to guide me when implemening in js --- implement-shell-tools/ls/ls.py | 49 ++++++++++++++-------------------- 1 file changed, 20 insertions(+), 29 deletions(-) diff --git a/implement-shell-tools/ls/ls.py b/implement-shell-tools/ls/ls.py index e46897d9..320bd0eb 100644 --- a/implement-shell-tools/ls/ls.py +++ b/implement-shell-tools/ls/ls.py @@ -1,45 +1,36 @@ # import process from "node:process"; -# import {promises as fs} from "node:fs"; -# import {program} from "commander"; +# import { promises as fs } from "node:fs"; +# import { program } from "commander"; # program -# .name("display-file-content") -# .description("Output the content of a file to the terminal") -# .argument("", "The file path to process") -# .option("-n", "Number the output lines") -# .option("-b","Number the non-blank output lines") +# .name("list-files-in-directory") +# .description("List all files and directories in a directory") +# .argument("", "The file path to process") +# .option("-1, --one", "Output one entry per line") +# .option("-a", "List all files & directories, including hidden ones"); # program.parse(); -# const paths = program.args; +# const path = program.args[0]; # const options = program.opts(); -# let lineNumber = 1; +# const directoryContent = await fs.readdir(path); -# for (const path of paths) { -# const filesContent = await fs.readFile(path, "utf-8"); +# let allContent = directoryContent; -# const lines = filesContent.split("\n"); - -# if (lines[lines.length - 1] === "") { -# lines.pop(); -# } +# if (!options.a) { +# allContent = directoryContent.filter(name => !name.startsWith(".")); +# } -# for (let line of lines) { -# if (options.n) { -# process.stdout.write(`${lineNumber} ${line}\n`); -# lineNumber++; -# } else if (options.b) { -# if (line != "") { -# process.stdout.write(`${lineNumber} ${line}\n`); -# lineNumber++; -# } else { -# process.stdout.write("\n"); -# } +# for (const item of allContent) { +# if (options.one) { +# process.stdout.write(item + "\n"); # } else { -# process.stdout.write(line + "\n"); +# process.stdout.write(item + " "); # } # } -# } + + + From 719bf239a47dc5a936a67a563e91ac261fc6dbc1 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Mon, 1 Dec 2025 15:46:17 +0000 Subject: [PATCH 24/69] define ls program meta data (name, options, paths etc) --- implement-shell-tools/ls/ls.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/implement-shell-tools/ls/ls.py b/implement-shell-tools/ls/ls.py index 320bd0eb..d8be728e 100644 --- a/implement-shell-tools/ls/ls.py +++ b/implement-shell-tools/ls/ls.py @@ -31,6 +31,17 @@ # } # } +import argparse + +parser = argparse.ArgumentParser( + prog="list-files-in-directory", + description="List all files and directories in a directory", +) + +parser.add_argument("-1", help="Output one entry per line", action="store_true") +parser.add_argument("-a", help="List all files & directories, including hidden ones", action="store_true") +parser.add_argument("paths", help="The file(s)/path(s) to read from", nargs="+") + From 2987f4b4560da0a4ef812912a44181b8370987ca Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Mon, 1 Dec 2025 15:46:52 +0000 Subject: [PATCH 25/69] read the comman line durign runtime --- implement-shell-tools/ls/ls.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/implement-shell-tools/ls/ls.py b/implement-shell-tools/ls/ls.py index d8be728e..9d91ddab 100644 --- a/implement-shell-tools/ls/ls.py +++ b/implement-shell-tools/ls/ls.py @@ -42,6 +42,10 @@ parser.add_argument("-a", help="List all files & directories, including hidden ones", action="store_true") parser.add_argument("paths", help="The file(s)/path(s) to read from", nargs="+") +args = parser.parse_args() + + + From 5b493c91949352310f8ab8c13961e9d576e33e4b Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Mon, 1 Dec 2025 15:47:58 +0000 Subject: [PATCH 26/69] handling one path with ls --- implement-shell-tools/ls/ls.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/implement-shell-tools/ls/ls.py b/implement-shell-tools/ls/ls.py index 9d91ddab..df2b3230 100644 --- a/implement-shell-tools/ls/ls.py +++ b/implement-shell-tools/ls/ls.py @@ -40,7 +40,7 @@ parser.add_argument("-1", help="Output one entry per line", action="store_true") parser.add_argument("-a", help="List all files & directories, including hidden ones", action="store_true") -parser.add_argument("paths", help="The file(s)/path(s) to read from", nargs="+") +parser.add_argument("path", help="The file path to read from") args = parser.parse_args() From 6c8a56737bbd9b2f1898ed4666e7001178623059 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Mon, 1 Dec 2025 15:52:19 +0000 Subject: [PATCH 27/69] import os library so that you can list files & dir inside a working dir --- implement-shell-tools/ls/ls.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/implement-shell-tools/ls/ls.py b/implement-shell-tools/ls/ls.py index df2b3230..32e658ad 100644 --- a/implement-shell-tools/ls/ls.py +++ b/implement-shell-tools/ls/ls.py @@ -32,6 +32,7 @@ # } import argparse +import os parser = argparse.ArgumentParser( prog="list-files-in-directory", @@ -44,6 +45,9 @@ args = parser.parse_args() +with open(args.path, "r") as f: + content = f.read() + From 83e99f3e73f079fb81f2185e02b25b6a54ad2922 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Mon, 1 Dec 2025 15:58:13 +0000 Subject: [PATCH 28/69] listing the files & dirs inside the working dir --- implement-shell-tools/ls/ls.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/implement-shell-tools/ls/ls.py b/implement-shell-tools/ls/ls.py index 32e658ad..1e13be48 100644 --- a/implement-shell-tools/ls/ls.py +++ b/implement-shell-tools/ls/ls.py @@ -40,13 +40,13 @@ ) parser.add_argument("-1", help="Output one entry per line", action="store_true") -parser.add_argument("-a", help="List all files & directories, including hidden ones", action="store_true") +parser.add_argument("-a", "--one", help="List all files & directories, including hidden ones", action="store_true") parser.add_argument("path", help="The file path to read from") args = parser.parse_args() -with open(args.path, "r") as f: - content = f.read() +content = os.listdir(args.path) + From 1d1ac0a908b58c0bd0daa1a2b9316e1f9cb9f1fa Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Mon, 1 Dec 2025 16:09:13 +0000 Subject: [PATCH 29/69] alogic in which the hidden files & dirs are filtered out (not shown) when -a option not added by end user --- implement-shell-tools/ls/ls.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/implement-shell-tools/ls/ls.py b/implement-shell-tools/ls/ls.py index 1e13be48..49cacc76 100644 --- a/implement-shell-tools/ls/ls.py +++ b/implement-shell-tools/ls/ls.py @@ -47,7 +47,10 @@ content = os.listdir(args.path) +all_content = content +if not args.a: + all_content(filter(lambda name: not name.startsWith("."))) From 9a40bd616973428612af15e94b9813f47bd90b0c Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Mon, 1 Dec 2025 16:12:01 +0000 Subject: [PATCH 30/69] logic added to handle one 1/one optition is added and if not all content to diplay in one line with spaces in between --- implement-shell-tools/ls/ls.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/implement-shell-tools/ls/ls.py b/implement-shell-tools/ls/ls.py index 49cacc76..58713684 100644 --- a/implement-shell-tools/ls/ls.py +++ b/implement-shell-tools/ls/ls.py @@ -52,6 +52,13 @@ if not args.a: all_content(filter(lambda name: not name.startsWith("."))) +for item in content: + if args.one: + print(item + "\n") + else: + print(item + " ") + + From 1e36528d898c8f5bd2cdb1e0c6e810dab5e8f254 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Mon, 1 Dec 2025 16:25:23 +0000 Subject: [PATCH 31/69] corrected syntactical errors --- implement-shell-tools/ls/ls.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/implement-shell-tools/ls/ls.py b/implement-shell-tools/ls/ls.py index 58713684..a208eb3c 100644 --- a/implement-shell-tools/ls/ls.py +++ b/implement-shell-tools/ls/ls.py @@ -39,8 +39,8 @@ description="List all files and directories in a directory", ) -parser.add_argument("-1", help="Output one entry per line", action="store_true") -parser.add_argument("-a", "--one", help="List all files & directories, including hidden ones", action="store_true") +parser.add_argument("-1", "--one", dest="one", help="Output one entry per line", action="store_true") +parser.add_argument("-a", help="List all files & directories, including hidden ones", action="store_true") parser.add_argument("path", help="The file path to read from") args = parser.parse_args() @@ -50,7 +50,7 @@ all_content = content if not args.a: - all_content(filter(lambda name: not name.startsWith("."))) + all_content = list(filter(lambda name: not name.startswith("."), content)) for item in content: if args.one: From 01ae017b6f88774e78d6d9570f2d3b42cf0cfc0c Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Mon, 1 Dec 2025 16:31:45 +0000 Subject: [PATCH 32/69] remove \n when -1 option selected to avoid duplication --- implement-shell-tools/ls/ls.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/implement-shell-tools/ls/ls.py b/implement-shell-tools/ls/ls.py index a208eb3c..9a25ab1c 100644 --- a/implement-shell-tools/ls/ls.py +++ b/implement-shell-tools/ls/ls.py @@ -54,7 +54,7 @@ for item in content: if args.one: - print(item + "\n") + print(item) else: print(item + " ") From 7ee60a5aa66d018690e268605423862c5f25ce53 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Mon, 1 Dec 2025 16:40:16 +0000 Subject: [PATCH 33/69] iterating over all_content instead to avoid diplaying hidden files when selecting -1 option --- implement-shell-tools/ls/ls.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/implement-shell-tools/ls/ls.py b/implement-shell-tools/ls/ls.py index 9a25ab1c..4dd6ada9 100644 --- a/implement-shell-tools/ls/ls.py +++ b/implement-shell-tools/ls/ls.py @@ -52,7 +52,7 @@ if not args.a: all_content = list(filter(lambda name: not name.startswith("."), content)) -for item in content: +for item in all_content: if args.one: print(item) else: From 0a68b74db95e4f6f7b171f3936bf00da4bcd9fe7 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Mon, 1 Dec 2025 16:43:04 +0000 Subject: [PATCH 34/69] remove js implementation of ls tool --- implement-shell-tools/ls/ls.py | 33 --------------------------------- 1 file changed, 33 deletions(-) diff --git a/implement-shell-tools/ls/ls.py b/implement-shell-tools/ls/ls.py index 4dd6ada9..73b29857 100644 --- a/implement-shell-tools/ls/ls.py +++ b/implement-shell-tools/ls/ls.py @@ -1,36 +1,3 @@ -# import process from "node:process"; -# import { promises as fs } from "node:fs"; -# import { program } from "commander"; - -# program -# .name("list-files-in-directory") -# .description("List all files and directories in a directory") -# .argument("", "The file path to process") -# .option("-1, --one", "Output one entry per line") -# .option("-a", "List all files & directories, including hidden ones"); - -# program.parse(); - -# const path = program.args[0]; - -# const options = program.opts(); - -# const directoryContent = await fs.readdir(path); - -# let allContent = directoryContent; - -# if (!options.a) { -# allContent = directoryContent.filter(name => !name.startsWith(".")); -# } - -# for (const item of allContent) { -# if (options.one) { -# process.stdout.write(item + "\n"); -# } else { -# process.stdout.write(item + " "); -# } -# } - import argparse import os From 82424f05dbdcbb157ac681b71dba95aff748f134 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Mon, 1 Dec 2025 18:11:27 +0000 Subject: [PATCH 35/69] create wc.py file with implementation of wc in js to use as guide when implmenting in py --- implement-shell-tools/wc/wc.py | 90 ++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 implement-shell-tools/wc/wc.py diff --git a/implement-shell-tools/wc/wc.py b/implement-shell-tools/wc/wc.py new file mode 100644 index 00000000..0d52a73f --- /dev/null +++ b/implement-shell-tools/wc/wc.py @@ -0,0 +1,90 @@ +# import { program } from "commander"; +# import { promises as fs } from "node:fs"; +# import process from "node:process"; +# import { stat } from "node:fs/promises"; + +# program +# .name("count-containing-lines-words-characters") +# .description("Counts lines, words or characters in a file (or all files) inside a directory") +# .option("-l, --line", "The number of lines in each file") +# .option("-w, --word", "The number of words in each file") +# .option("-c, --character", "The number of characters in each file") +# .argument("", "The file path to process"); + +# program.parse(); + +# const argv = program.args; + +# const options = program.opts(); + + +# function counter(item) { +# const lines = item.trim().split("\n").length; +# const words = item.split(/\s+/).filter(Boolean).length; +# const characters = item.length; +# return { lines, words, characters }; +# } + +# let totalLines = 0; +# let totalWords = 0; +# let totalCharacters = 0; +# let fileCount = 0; + +# for (const path of argv) { +# const pathInfo = await stat(path); + +# if (pathInfo.isFile()) { +# const content = await fs.readFile(path, "utf-8"); +# const stats = counter(content); +# if (options.line) { +# console.log(`${stats.lines} ${path}`); +# } else if (options.word) { +# console.log(`${stats.words} ${path}`); +# } else if (options.character) { +# console.log(`${stats.characters} ${path}`); +# } else { +# console.log(`${stats.lines} ${stats.words} ${stats.characters} ${path}`); +# } + +# totalLines += stats.lines; +# totalWords += stats.words; +# totalCharacters += stats.characters; +# fileCount++; + +# } else if (pathInfo.isDirectory()) { +# const files = await fs.readdir(path); +# for (const file of files) { +# const filePath = `${path}/${file}`; +# const fileContent = await fs.readFile(filePath, "utf-8"); +# const stats = counter(fileContent); + +# if (options.line) { +# console.log(`${stats.lines} ${filePath}`); +# } else if (options.word) { +# console.log(`${stats.words} ${filePath}`); +# } else if (options.character) { +# console.log(`${stats.characters} ${filePath}`); +# } else { +# console.log(`${stats.lines} ${stats.words} ${stats.characters} ${filePath}`); +# } + +# totalLines += stats.lines; +# totalWords += stats.words; +# totalCharacters += stats.characters; +# fileCount++; +# } +# } + +# } + +# if (fileCount > 1) { +# if (options.line) { +# console.log(`${totalLines} total`); +# } else if (options.word) { +# console.log(`${totalWords} total`); +# } else if (options.character) { +# console.log(`${totalCharacters} total`); +# } else { +# console.log(`${totalLines} ${totalWords} ${totalCharacters} total`); +# } +# } From a0828391ed49bac567fd5e77b862fc148dc3bcbc Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Mon, 1 Dec 2025 18:20:16 +0000 Subject: [PATCH 36/69] define program meta data: name, description, options, arguments/paths etc --- implement-shell-tools/wc/wc.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/implement-shell-tools/wc/wc.py b/implement-shell-tools/wc/wc.py index 0d52a73f..b6348e47 100644 --- a/implement-shell-tools/wc/wc.py +++ b/implement-shell-tools/wc/wc.py @@ -88,3 +88,17 @@ # console.log(`${totalLines} ${totalWords} ${totalCharacters} total`); # } # } + +import argparse + +parser = argparse.ArgumentParser( + prog="counter", + description="Counts lines, words or characters in a file (or all files) inside a directory", +) + +parser.add_argument("-l", "--line", dest="line", help="The number of lines in each file", action="store_true") +parser.add_argument("-w", "---word", dest="word", help="The number of words in each file", action="store_true") +parser.add_argument("-c", "--char", dest="char", help="The number of characters in each file") +parser.add_argument("paths", help="The file(s)/path(s) to read from", nargs="+") + +args = parser.parse_args() From 4aad5aba8eebcdb9d57a377c57f7c236e3f4a52d Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Tue, 2 Dec 2025 18:29:28 +0000 Subject: [PATCH 37/69] building counter function --- implement-shell-tools/wc/wc.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/implement-shell-tools/wc/wc.py b/implement-shell-tools/wc/wc.py index b6348e47..90884fb9 100644 --- a/implement-shell-tools/wc/wc.py +++ b/implement-shell-tools/wc/wc.py @@ -102,3 +102,17 @@ parser.add_argument("paths", help="The file(s)/path(s) to read from", nargs="+") args = parser.parse_args() + +def counter(item): + lines = len(item.trim().split("\n")) + words = item.split() + + + +for path in args.paths: + with open(path, "r") as f: + content = f.read() + if args.l: + + + From 914cfda699c78715dbadf4bf89a2d56fa4d71fe4 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Fri, 5 Dec 2025 20:23:10 +0000 Subject: [PATCH 38/69] added counter function to count words, lines and characters from a path(s) --- implement-shell-tools/wc/wc.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/implement-shell-tools/wc/wc.py b/implement-shell-tools/wc/wc.py index 90884fb9..cbd793aa 100644 --- a/implement-shell-tools/wc/wc.py +++ b/implement-shell-tools/wc/wc.py @@ -106,8 +106,15 @@ def counter(item): lines = len(item.trim().split("\n")) words = item.split() + characters = len(item) + return {lines, words, characters} +total_lines = 0 +total_words = 0 +total_characters = 0 +file_count = 0 + for path in args.paths: with open(path, "r") as f: From c70d7d931eedfb4c474cd11b34eb012bef4661b9 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Fri, 5 Dec 2025 20:36:19 +0000 Subject: [PATCH 39/69] add skeleton for flags/option cases --- implement-shell-tools/wc/wc.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/implement-shell-tools/wc/wc.py b/implement-shell-tools/wc/wc.py index cbd793aa..14f8a06f 100644 --- a/implement-shell-tools/wc/wc.py +++ b/implement-shell-tools/wc/wc.py @@ -119,7 +119,14 @@ def counter(item): for path in args.paths: with open(path, "r") as f: content = f.read() - if args.l: - + stats = counter(content) + if args.line: + print(f"{lines} {path}") + elif args.word: + print() + elif args.char: + print() + else: + print("") From d996f5b22e6e3b8fe939adf8b9dc8c2ee5605529 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Fri, 5 Dec 2025 20:40:13 +0000 Subject: [PATCH 40/69] corrected bugs in counter function --- implement-shell-tools/wc/wc.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/implement-shell-tools/wc/wc.py b/implement-shell-tools/wc/wc.py index 14f8a06f..269e8be1 100644 --- a/implement-shell-tools/wc/wc.py +++ b/implement-shell-tools/wc/wc.py @@ -104,10 +104,10 @@ args = parser.parse_args() def counter(item): - lines = len(item.trim().split("\n")) - words = item.split() + lines = len(item.strip().split("\n")) + words = len(item.split()) characters = len(item) - return {lines, words, characters} + return {"lines": lines, "words": words, "characters": characters} total_lines = 0 @@ -121,7 +121,7 @@ def counter(item): content = f.read() stats = counter(content) if args.line: - print(f"{lines} {path}") + print(f"{stats[lines]} {path}") elif args.word: print() elif args.char: From 72c9e8e2d6aa96733d1a9ffcc1f497b304f93cc3 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Fri, 5 Dec 2025 20:44:42 +0000 Subject: [PATCH 41/69] updated output message for when a particular option is added by end user --- implement-shell-tools/wc/wc.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/implement-shell-tools/wc/wc.py b/implement-shell-tools/wc/wc.py index 269e8be1..f9091d61 100644 --- a/implement-shell-tools/wc/wc.py +++ b/implement-shell-tools/wc/wc.py @@ -121,12 +121,12 @@ def counter(item): content = f.read() stats = counter(content) if args.line: - print(f"{stats[lines]} {path}") + print(f"{stats['lines']} {path}") elif args.word: - print() + print(f"{stats['words']} {path}") elif args.char: - print() + print(f"{stats['characters']} {path}") else: - print("") + print(f"{stats['lines']} {stats['words']} {stats['characters']} {path}") From dc375e6e4cf70ec2a33762e63d9d38f20b9f99bb Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Fri, 5 Dec 2025 20:47:40 +0000 Subject: [PATCH 42/69] importing os so that we could handle when a path is file vs when a path is a dir --- implement-shell-tools/wc/wc.py | 1 + 1 file changed, 1 insertion(+) diff --git a/implement-shell-tools/wc/wc.py b/implement-shell-tools/wc/wc.py index f9091d61..43627dd9 100644 --- a/implement-shell-tools/wc/wc.py +++ b/implement-shell-tools/wc/wc.py @@ -90,6 +90,7 @@ # } import argparse +import os parser = argparse.ArgumentParser( prog="counter", From c4d27960456f5e6cbc456bccc9969c26d91d5131 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Fri, 5 Dec 2025 20:51:44 +0000 Subject: [PATCH 43/69] handling when path is file --- implement-shell-tools/wc/wc.py | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/implement-shell-tools/wc/wc.py b/implement-shell-tools/wc/wc.py index 43627dd9..3e4d244a 100644 --- a/implement-shell-tools/wc/wc.py +++ b/implement-shell-tools/wc/wc.py @@ -118,16 +118,17 @@ def counter(item): for path in args.paths: - with open(path, "r") as f: - content = f.read() - stats = counter(content) - if args.line: - print(f"{stats['lines']} {path}") - elif args.word: - print(f"{stats['words']} {path}") - elif args.char: - print(f"{stats['characters']} {path}") - else: - print(f"{stats['lines']} {stats['words']} {stats['characters']} {path}") + if os.path.isfile(path): + with open(path, "r") as f: + content = f.read() + stats = counter(content) + if args.line: + print(f"{stats['lines']} {path}") + elif args.word: + print(f"{stats['words']} {path}") + elif args.char: + print(f"{stats['characters']} {path}") + else: + print(f"{stats['lines']} {stats['words']} {stats['characters']} {path}") From d4cd590c045d104a6d027fac664c05a7c542ca43 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Fri, 5 Dec 2025 21:03:30 +0000 Subject: [PATCH 44/69] flesh out lofic for when path is a dir --- implement-shell-tools/wc/wc.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/implement-shell-tools/wc/wc.py b/implement-shell-tools/wc/wc.py index 3e4d244a..8b2683dc 100644 --- a/implement-shell-tools/wc/wc.py +++ b/implement-shell-tools/wc/wc.py @@ -130,5 +130,25 @@ def counter(item): print(f"{stats['characters']} {path}") else: print(f"{stats['lines']} {stats['words']} {stats['characters']} {path}") + elif os.path.isdir(path): + directory = "folder" + + for file in os.listdir(directory): + path = os.path.join(directory, file) + + if os.path.isfile(path): + with open(path, "r") as f: + content = f.read() + stats = counter(content) + if args.line: + print(f"{stats['lines']} {path}") + elif args.word: + print(f"{stats['words']} {path}") + elif args.char: + print(f"{stats['characters']} {path}") + else: + print(f"{stats['lines']} {stats['words']} {stats['characters']} {path}") + + From 76a8647b2e89384b5db88920893327825e2e69c5 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Fri, 5 Dec 2025 21:49:05 +0000 Subject: [PATCH 45/69] moving bits of code around and updating var so that in the case of dir a total is diplayed to console --- implement-shell-tools/wc/wc.py | 47 +++++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/implement-shell-tools/wc/wc.py b/implement-shell-tools/wc/wc.py index 8b2683dc..fe5953d5 100644 --- a/implement-shell-tools/wc/wc.py +++ b/implement-shell-tools/wc/wc.py @@ -98,8 +98,8 @@ ) parser.add_argument("-l", "--line", dest="line", help="The number of lines in each file", action="store_true") -parser.add_argument("-w", "---word", dest="word", help="The number of words in each file", action="store_true") -parser.add_argument("-c", "--char", dest="char", help="The number of characters in each file") +parser.add_argument("-w", "--word", dest="word", help="The number of words in each file", action="store_true") +parser.add_argument("-c", "--char", dest="char", help="The number of characters in each file", action="store_true") parser.add_argument("paths", help="The file(s)/path(s) to read from", nargs="+") args = parser.parse_args() @@ -130,24 +130,47 @@ def counter(item): print(f"{stats['characters']} {path}") else: print(f"{stats['lines']} {stats['words']} {stats['characters']} {path}") - elif os.path.isdir(path): - directory = "folder" - for file in os.listdir(directory): - path = os.path.join(directory, file) + total_lines += stats['lines'] + total_words += stats['words'] + total_characters += stats['characters'] + file_count += 1 + + elif os.path.isdir(path): + for file in os.listdir(path): + file_path = os.path.join(path, file) - if os.path.isfile(path): - with open(path, "r") as f: + if os.path.isfile(file_path): + with open(file_path, "r") as f: content = f.read() stats = counter(content) if args.line: - print(f"{stats['lines']} {path}") + print(f"{stats['lines']} {file_path}") elif args.word: - print(f"{stats['words']} {path}") + print(f"{stats['words']} {file_path}") elif args.char: - print(f"{stats['characters']} {path}") + print(f"{stats['characters']} {file_path}") else: - print(f"{stats['lines']} {stats['words']} {stats['characters']} {path}") + print(f"{stats['lines']} {stats['words']} {stats['characters']} {file_path}") + + total_lines += stats['lines'] + total_words += stats['words'] + total_characters += stats['characters'] + file_count += 1 + + + + + +if file_count > 1: + if args.line: + print(f"{total_lines} total") + elif args.word: + print(f"{total_words} total") + elif args.char: + print(f"{total_characters} total") + else: + print(f"{total_lines} {total_words} {total_characters} total") From 731c907a8240c0636ea192da08e645f5e51db2f9 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Wed, 14 Jan 2026 20:18:47 +0000 Subject: [PATCH 46/69] replace reading files to avoid unnessary memoery usage --- implement-shell-tools/cat/cat.py | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/implement-shell-tools/cat/cat.py b/implement-shell-tools/cat/cat.py index ceaacb1e..3c3adeca 100644 --- a/implement-shell-tools/cat/cat.py +++ b/implement-shell-tools/cat/cat.py @@ -15,13 +15,8 @@ for path in args.paths: with open(path, "r") as f: - content = f.read() - - lines = content.split("\n") - if lines[len(lines) - 1] == "": - lines.pop() - - for line in lines: + for line in f: + line = line.rstrip("\n") if args.n: print(f"{line_number} {line}") line_number += 1 From baadd851f06f1dd694a31fcad803c454ffcd8e67 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Wed, 14 Jan 2026 20:32:26 +0000 Subject: [PATCH 47/69] correct my code to ensuring formatting match the actual act with -n flag --- implement-shell-tools/cat/cat.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/implement-shell-tools/cat/cat.py b/implement-shell-tools/cat/cat.py index 3c3adeca..462251a2 100644 --- a/implement-shell-tools/cat/cat.py +++ b/implement-shell-tools/cat/cat.py @@ -18,7 +18,7 @@ for line in f: line = line.rstrip("\n") if args.n: - print(f"{line_number} {line}") + print(f"{line_number:>6} {line}") line_number += 1 elif args.b: if line != "": From 312abeb3ca543cc8d7ea733f158baea077103003 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Wed, 14 Jan 2026 20:56:30 +0000 Subject: [PATCH 48/69] handling cases when -a flag is added to ls to show the current and parents dir(s) --- implement-shell-tools/ls/ls.py | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/implement-shell-tools/ls/ls.py b/implement-shell-tools/ls/ls.py index 73b29857..e616705b 100644 --- a/implement-shell-tools/ls/ls.py +++ b/implement-shell-tools/ls/ls.py @@ -12,18 +12,13 @@ args = parser.parse_args() -content = os.listdir(args.path) +if os.path.isdir(path): + items = os.listdir(path) -all_content = content + if args.a: + items = ['.', '..'] + items -if not args.a: - all_content = list(filter(lambda name: not name.startswith("."), content)) - -for item in all_content: - if args.one: - print(item) - else: - print(item + " ") + From 0b90dbc4ed936505e2600f70853ca2835d2c8552 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Wed, 14 Jan 2026 20:58:25 +0000 Subject: [PATCH 49/69] handle cases when -a flag not selected --- implement-shell-tools/ls/ls.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/implement-shell-tools/ls/ls.py b/implement-shell-tools/ls/ls.py index e616705b..c55c1287 100644 --- a/implement-shell-tools/ls/ls.py +++ b/implement-shell-tools/ls/ls.py @@ -18,6 +18,9 @@ if args.a: items = ['.', '..'] + items + if not args.a: + items = [item for item in items if not item.startswith(".")] + From 0bd31b07f3fb9303aede52412121a06943098bec Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Wed, 14 Jan 2026 21:02:09 +0000 Subject: [PATCH 50/69] handle when -1 flag is added and when it's not --- implement-shell-tools/ls/ls.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/implement-shell-tools/ls/ls.py b/implement-shell-tools/ls/ls.py index c55c1287..09c0ea42 100644 --- a/implement-shell-tools/ls/ls.py +++ b/implement-shell-tools/ls/ls.py @@ -20,6 +20,17 @@ if not args.a: items = [item for item in items if not item.startswith(".")] + + + for i, item in enumerate(items): + if args.one: + print(item) + else: + print(item, end=" ") + if not args.one: + print() + else: + print(path) From a8f7a8df2bee4f137f8f8ff6a13324352d27beeb Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Wed, 14 Jan 2026 21:10:36 +0000 Subject: [PATCH 51/69] change 3rd parser.add_argument to allow several paths with default --- implement-shell-tools/ls/ls.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/implement-shell-tools/ls/ls.py b/implement-shell-tools/ls/ls.py index 09c0ea42..c91d2f39 100644 --- a/implement-shell-tools/ls/ls.py +++ b/implement-shell-tools/ls/ls.py @@ -8,7 +8,7 @@ parser.add_argument("-1", "--one", dest="one", help="Output one entry per line", action="store_true") parser.add_argument("-a", help="List all files & directories, including hidden ones", action="store_true") -parser.add_argument("path", help="The file path to read from") +parser.add_argument("paths", nargs="*", default=["."], help="The file path to read from") args = parser.parse_args() From 8a650642218f0efb0c8e6c95b4d2ffccf98215e3 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Wed, 14 Jan 2026 21:11:17 +0000 Subject: [PATCH 52/69] remove reduntant line --- implement-shell-tools/ls/ls.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/implement-shell-tools/ls/ls.py b/implement-shell-tools/ls/ls.py index c91d2f39..b895a2da 100644 --- a/implement-shell-tools/ls/ls.py +++ b/implement-shell-tools/ls/ls.py @@ -29,9 +29,7 @@ print(item, end=" ") if not args.one: print() - else: - print(path) - + From a6642bbe71bfeef4f7e68e9b3875b57ebd2f8a8e Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Wed, 14 Jan 2026 21:18:46 +0000 Subject: [PATCH 53/69] improving the quality of code for -a flag code block and adding a final else --- implement-shell-tools/ls/ls.py | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/implement-shell-tools/ls/ls.py b/implement-shell-tools/ls/ls.py index b895a2da..9e2304c3 100644 --- a/implement-shell-tools/ls/ls.py +++ b/implement-shell-tools/ls/ls.py @@ -12,23 +12,25 @@ args = parser.parse_args() -if os.path.isdir(path): - items = os.listdir(path) +for path in args.paths: + if os.path.isdir(path): + items = os.listdir(path) - if args.a: - items = ['.', '..'] + items - - if not args.a: - items = [item for item in items if not item.startswith(".")] - - - for i, item in enumerate(items): - if args.one: - print(item) + if args.a: + items = ['.', '..'] + items else: - print(item, end=" ") - if not args.one: - print() + items = [item for item in items if not item.startswith(".")] + + for i, item in enumerate(items): + if args.one: + print(item) + else: + print(item, end=" ") + if not args.one: + print() + + else: + print(path) From 6a5281e0d0c31c602cc154fc39e482bbc063cd09 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Wed, 14 Jan 2026 21:21:27 +0000 Subject: [PATCH 54/69] simplify the for loop --- implement-shell-tools/ls/ls.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/implement-shell-tools/ls/ls.py b/implement-shell-tools/ls/ls.py index 9e2304c3..7bfa408f 100644 --- a/implement-shell-tools/ls/ls.py +++ b/implement-shell-tools/ls/ls.py @@ -21,14 +21,13 @@ else: items = [item for item in items if not item.startswith(".")] - for i, item in enumerate(items): + for item in items: if args.one: print(item) else: print(item, end=" ") if not args.one: print() - else: print(path) From 683fc0cbd84dfd70ce10b3edf66b83a0d355113d Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Wed, 14 Jan 2026 21:22:57 +0000 Subject: [PATCH 55/69] adding double spaces for the -one flag to match the format of the actual ls with -1 flag --- implement-shell-tools/ls/ls.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/implement-shell-tools/ls/ls.py b/implement-shell-tools/ls/ls.py index 7bfa408f..19aec428 100644 --- a/implement-shell-tools/ls/ls.py +++ b/implement-shell-tools/ls/ls.py @@ -25,7 +25,7 @@ if args.one: print(item) else: - print(item, end=" ") + print(item, end=" ") if not args.one: print() else: From b95cf8e6aace91a23974ac2cbef450006ed259ba Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Wed, 14 Jan 2026 21:24:37 +0000 Subject: [PATCH 56/69] adding sorting method so that it matches the actual ls output order --- implement-shell-tools/ls/ls.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/implement-shell-tools/ls/ls.py b/implement-shell-tools/ls/ls.py index 19aec428..ce9a791f 100644 --- a/implement-shell-tools/ls/ls.py +++ b/implement-shell-tools/ls/ls.py @@ -20,6 +20,8 @@ items = ['.', '..'] + items else: items = [item for item in items if not item.startswith(".")] + + items.sort() for item in items: if args.one: From e3a7ce3c32f14d1f4b9b909dce5ed957f18766a9 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Wed, 14 Jan 2026 21:30:21 +0000 Subject: [PATCH 57/69] discarding the redantant commented js implementation --- implement-shell-tools/wc/wc.py | 90 ---------------------------------- 1 file changed, 90 deletions(-) diff --git a/implement-shell-tools/wc/wc.py b/implement-shell-tools/wc/wc.py index fe5953d5..ce3eae7f 100644 --- a/implement-shell-tools/wc/wc.py +++ b/implement-shell-tools/wc/wc.py @@ -1,93 +1,3 @@ -# import { program } from "commander"; -# import { promises as fs } from "node:fs"; -# import process from "node:process"; -# import { stat } from "node:fs/promises"; - -# program -# .name("count-containing-lines-words-characters") -# .description("Counts lines, words or characters in a file (or all files) inside a directory") -# .option("-l, --line", "The number of lines in each file") -# .option("-w, --word", "The number of words in each file") -# .option("-c, --character", "The number of characters in each file") -# .argument("", "The file path to process"); - -# program.parse(); - -# const argv = program.args; - -# const options = program.opts(); - - -# function counter(item) { -# const lines = item.trim().split("\n").length; -# const words = item.split(/\s+/).filter(Boolean).length; -# const characters = item.length; -# return { lines, words, characters }; -# } - -# let totalLines = 0; -# let totalWords = 0; -# let totalCharacters = 0; -# let fileCount = 0; - -# for (const path of argv) { -# const pathInfo = await stat(path); - -# if (pathInfo.isFile()) { -# const content = await fs.readFile(path, "utf-8"); -# const stats = counter(content); -# if (options.line) { -# console.log(`${stats.lines} ${path}`); -# } else if (options.word) { -# console.log(`${stats.words} ${path}`); -# } else if (options.character) { -# console.log(`${stats.characters} ${path}`); -# } else { -# console.log(`${stats.lines} ${stats.words} ${stats.characters} ${path}`); -# } - -# totalLines += stats.lines; -# totalWords += stats.words; -# totalCharacters += stats.characters; -# fileCount++; - -# } else if (pathInfo.isDirectory()) { -# const files = await fs.readdir(path); -# for (const file of files) { -# const filePath = `${path}/${file}`; -# const fileContent = await fs.readFile(filePath, "utf-8"); -# const stats = counter(fileContent); - -# if (options.line) { -# console.log(`${stats.lines} ${filePath}`); -# } else if (options.word) { -# console.log(`${stats.words} ${filePath}`); -# } else if (options.character) { -# console.log(`${stats.characters} ${filePath}`); -# } else { -# console.log(`${stats.lines} ${stats.words} ${stats.characters} ${filePath}`); -# } - -# totalLines += stats.lines; -# totalWords += stats.words; -# totalCharacters += stats.characters; -# fileCount++; -# } -# } - -# } - -# if (fileCount > 1) { -# if (options.line) { -# console.log(`${totalLines} total`); -# } else if (options.word) { -# console.log(`${totalWords} total`); -# } else if (options.character) { -# console.log(`${totalCharacters} total`); -# } else { -# console.log(`${totalLines} ${totalWords} ${totalCharacters} total`); -# } -# } import argparse import os From 82a68007373c8fe99c862f63e42642ec25b8bf02 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Wed, 14 Jan 2026 21:47:49 +0000 Subject: [PATCH 58/69] setting up a helper function that handles reading files, printing stats and updating total --- implement-shell-tools/wc/wc.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/implement-shell-tools/wc/wc.py b/implement-shell-tools/wc/wc.py index ce3eae7f..41cc41fc 100644 --- a/implement-shell-tools/wc/wc.py +++ b/implement-shell-tools/wc/wc.py @@ -21,6 +21,10 @@ def counter(item): return {"lines": lines, "words": words, "characters": characters} +def process_file(file_path): + global total_lines, total_words, total_characters, file_count + + total_lines = 0 total_words = 0 total_characters = 0 From e9f2a54317fcd9c62b8219dfeb2335d6b7d413d8 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Wed, 14 Jan 2026 21:51:38 +0000 Subject: [PATCH 59/69] moving code into the helper function proccess_file --- implement-shell-tools/wc/wc.py | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/implement-shell-tools/wc/wc.py b/implement-shell-tools/wc/wc.py index 41cc41fc..0684f80f 100644 --- a/implement-shell-tools/wc/wc.py +++ b/implement-shell-tools/wc/wc.py @@ -24,6 +24,20 @@ def counter(item): def process_file(file_path): global total_lines, total_words, total_characters, file_count + with open(path, "r") as f: + content = f.read() + + stats = counter(content) + + if args.line: + print(f"{stats['lines']} {path}") + elif args.word: + print(f"{stats['words']} {path}") + elif args.char: + print(f"{stats['characters']} {path}") + else: + print(f"{stats['lines']} {stats['words']} {stats['characters']} {path}") + total_lines = 0 total_words = 0 @@ -33,17 +47,9 @@ def process_file(file_path): for path in args.paths: if os.path.isfile(path): - with open(path, "r") as f: - content = f.read() - stats = counter(content) - if args.line: - print(f"{stats['lines']} {path}") - elif args.word: - print(f"{stats['words']} {path}") - elif args.char: - print(f"{stats['characters']} {path}") - else: - print(f"{stats['lines']} {stats['words']} {stats['characters']} {path}") + + + total_lines += stats['lines'] total_words += stats['words'] @@ -57,7 +63,7 @@ def process_file(file_path): if os.path.isfile(file_path): with open(file_path, "r") as f: content = f.read() - stats = counter(content) + if args.line: print(f"{stats['lines']} {file_path}") elif args.word: From 9f5649ffeb6d98a4d5462ae615540c6a08bcb57b Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Wed, 14 Jan 2026 21:52:39 +0000 Subject: [PATCH 60/69] update the default paremeter of the helper function process_file to file_path instead --- implement-shell-tools/wc/wc.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/implement-shell-tools/wc/wc.py b/implement-shell-tools/wc/wc.py index 0684f80f..3c9e9a18 100644 --- a/implement-shell-tools/wc/wc.py +++ b/implement-shell-tools/wc/wc.py @@ -30,13 +30,13 @@ def process_file(file_path): stats = counter(content) if args.line: - print(f"{stats['lines']} {path}") + print(f"{stats['lines']} {file_path}}") elif args.word: - print(f"{stats['words']} {path}") + print(f"{stats['words']} {file_path}}") elif args.char: - print(f"{stats['characters']} {path}") + print(f"{stats['characters']} {file_path}}") else: - print(f"{stats['lines']} {stats['words']} {stats['characters']} {path}") + print(f"{stats['lines']} {stats['words']} {stats['characters']} {file_path}}") total_lines = 0 From 14fca64cf0c380a79b3f571e4168373e03306391 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Wed, 14 Jan 2026 21:54:02 +0000 Subject: [PATCH 61/69] moving code inside helper function process_file --- implement-shell-tools/wc/wc.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/implement-shell-tools/wc/wc.py b/implement-shell-tools/wc/wc.py index 3c9e9a18..c520eee5 100644 --- a/implement-shell-tools/wc/wc.py +++ b/implement-shell-tools/wc/wc.py @@ -36,7 +36,13 @@ def process_file(file_path): elif args.char: print(f"{stats['characters']} {file_path}}") else: - print(f"{stats['lines']} {stats['words']} {stats['characters']} {file_path}}") + print(f"{stats['lines']} {stats['words']} {stats['characters']} {file_path}") + + + total_lines += stats['lines'] + total_words += stats['words'] + total_characters += stats['characters'] + file_count += 1 total_lines = 0 @@ -51,11 +57,6 @@ def process_file(file_path): - total_lines += stats['lines'] - total_words += stats['words'] - total_characters += stats['characters'] - file_count += 1 - elif os.path.isdir(path): for file in os.listdir(path): file_path = os.path.join(path, file) From 140467f3babfdf417f98044bd5d91d9333163655 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Wed, 14 Jan 2026 21:57:29 +0000 Subject: [PATCH 62/69] get rid of repetetive code --- implement-shell-tools/wc/wc.py | 32 +++++++++----------------------- 1 file changed, 9 insertions(+), 23 deletions(-) diff --git a/implement-shell-tools/wc/wc.py b/implement-shell-tools/wc/wc.py index c520eee5..de53b0f2 100644 --- a/implement-shell-tools/wc/wc.py +++ b/implement-shell-tools/wc/wc.py @@ -14,6 +14,13 @@ args = parser.parse_args() + +total_lines = 0 +total_words = 0 +total_characters = 0 +file_count = 0 + + def counter(item): lines = len(item.strip().split("\n")) words = len(item.split()) @@ -38,46 +45,25 @@ def process_file(file_path): else: print(f"{stats['lines']} {stats['words']} {stats['characters']} {file_path}") - total_lines += stats['lines'] total_words += stats['words'] total_characters += stats['characters'] file_count += 1 -total_lines = 0 -total_words = 0 -total_characters = 0 -file_count = 0 for path in args.paths: if os.path.isfile(path): - - - - + process_file(path) elif os.path.isdir(path): for file in os.listdir(path): file_path = os.path.join(path, file) - if os.path.isfile(file_path): with open(file_path, "r") as f: content = f.read() - if args.line: - print(f"{stats['lines']} {file_path}") - elif args.word: - print(f"{stats['words']} {file_path}") - elif args.char: - print(f"{stats['characters']} {file_path}") - else: - print(f"{stats['lines']} {stats['words']} {stats['characters']} {file_path}") - - total_lines += stats['lines'] - total_words += stats['words'] - total_characters += stats['characters'] - file_count += 1 + From 088df21f72612c002b209cb5f5343f3b1bf55e7f Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Wed, 14 Jan 2026 22:00:34 +0000 Subject: [PATCH 63/69] edit code for when path is dir --- implement-shell-tools/wc/wc.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/implement-shell-tools/wc/wc.py b/implement-shell-tools/wc/wc.py index de53b0f2..c7d76669 100644 --- a/implement-shell-tools/wc/wc.py +++ b/implement-shell-tools/wc/wc.py @@ -60,8 +60,8 @@ def process_file(file_path): for file in os.listdir(path): file_path = os.path.join(path, file) if os.path.isfile(file_path): - with open(file_path, "r") as f: - content = f.read() + process_file(file_path) + From 4b2801f96c4704a5ea9436a2e22dfd861eed743e Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Wed, 14 Jan 2026 22:02:22 +0000 Subject: [PATCH 64/69] change parameter to file_path to get rid of bug --- implement-shell-tools/wc/wc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/implement-shell-tools/wc/wc.py b/implement-shell-tools/wc/wc.py index c7d76669..f1c70a66 100644 --- a/implement-shell-tools/wc/wc.py +++ b/implement-shell-tools/wc/wc.py @@ -31,7 +31,7 @@ def counter(item): def process_file(file_path): global total_lines, total_words, total_characters, file_count - with open(path, "r") as f: + with open(file_path, "r") as f: content = f.read() stats = counter(content) From 655102675d4f76a9b4e60942af6177e1a0ccc826 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Wed, 14 Jan 2026 22:03:23 +0000 Subject: [PATCH 65/69] getting rid of all extra } --- implement-shell-tools/wc/wc.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/implement-shell-tools/wc/wc.py b/implement-shell-tools/wc/wc.py index f1c70a66..a186e31d 100644 --- a/implement-shell-tools/wc/wc.py +++ b/implement-shell-tools/wc/wc.py @@ -37,11 +37,11 @@ def process_file(file_path): stats = counter(content) if args.line: - print(f"{stats['lines']} {file_path}}") + print(f"{stats['lines']} {file_path}") elif args.word: - print(f"{stats['words']} {file_path}}") + print(f"{stats['words']} {file_path}") elif args.char: - print(f"{stats['characters']} {file_path}}") + print(f"{stats['characters']} {file_path}") else: print(f"{stats['lines']} {stats['words']} {stats['characters']} {file_path}") From b1b1669f2abb8b3b9e45be46a134a39d681ec2d1 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Wed, 14 Jan 2026 23:29:47 +0000 Subject: [PATCH 66/69] replace the double spacing with \t to cause the "double spacing" effect ls do when listing files in a dir --- implement-shell-tools/ls/ls.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/implement-shell-tools/ls/ls.py b/implement-shell-tools/ls/ls.py index ce9a791f..c2439903 100644 --- a/implement-shell-tools/ls/ls.py +++ b/implement-shell-tools/ls/ls.py @@ -27,7 +27,7 @@ if args.one: print(item) else: - print(item, end=" ") + print(item, end="\t") if not args.one: print() else: From 5158913ae37bf6a40431e0e22e45301e64c9920e Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Wed, 14 Jan 2026 23:59:34 +0000 Subject: [PATCH 67/69] change logic to elminate the need for using keyword "global" --- implement-shell-tools/wc/wc.py | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/implement-shell-tools/wc/wc.py b/implement-shell-tools/wc/wc.py index a186e31d..d4887ba4 100644 --- a/implement-shell-tools/wc/wc.py +++ b/implement-shell-tools/wc/wc.py @@ -29,8 +29,6 @@ def counter(item): def process_file(file_path): - global total_lines, total_words, total_characters, file_count - with open(file_path, "r") as f: content = f.read() @@ -45,12 +43,12 @@ def process_file(file_path): else: print(f"{stats['lines']} {stats['words']} {stats['characters']} {file_path}") - total_lines += stats['lines'] - total_words += stats['words'] - total_characters += stats['characters'] - file_count += 1 - + total['lines'] += stats['lines'] + total['words'] += stats['words'] + total['characters'] += stats['characters'] + total['files'] += 1 +total = {'lines': 0, 'words': 0, 'characters': 0, 'files': 0} for path in args.paths: @@ -69,15 +67,15 @@ def process_file(file_path): -if file_count > 1: +if total['files'] > 1: if args.line: - print(f"{total_lines} total") + print(f"{total['lines']} total") elif args.word: - print(f"{total_words} total") + print(f"{total['words']} total") elif args.char: - print(f"{total_characters} total") + print(f"{total['characters']} total") else: - print(f"{total_lines} {total_words} {total_characters} total") + print(f"{total['lines']} {total['words']} {total['characters']} total") From 92929e01f3a9137356d51746aeaac1ffcbbe9ac3 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Thu, 15 Jan 2026 00:04:14 +0000 Subject: [PATCH 68/69] move total before helper function process_file otherwise error is thrown and get rid of code no longer in use --- implement-shell-tools/wc/wc.py | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/implement-shell-tools/wc/wc.py b/implement-shell-tools/wc/wc.py index d4887ba4..5e15c66c 100644 --- a/implement-shell-tools/wc/wc.py +++ b/implement-shell-tools/wc/wc.py @@ -14,12 +14,7 @@ args = parser.parse_args() - -total_lines = 0 -total_words = 0 -total_characters = 0 -file_count = 0 - +total = {'lines': 0, 'words': 0, 'characters': 0, 'files': 0} def counter(item): lines = len(item.strip().split("\n")) @@ -28,7 +23,7 @@ def counter(item): return {"lines": lines, "words": words, "characters": characters} -def process_file(file_path): +def process_file(file_path, total): with open(file_path, "r") as f: content = f.read() @@ -48,17 +43,16 @@ def process_file(file_path): total['characters'] += stats['characters'] total['files'] += 1 -total = {'lines': 0, 'words': 0, 'characters': 0, 'files': 0} for path in args.paths: if os.path.isfile(path): - process_file(path) + process_file(path, total) elif os.path.isdir(path): for file in os.listdir(path): file_path = os.path.join(path, file) if os.path.isfile(file_path): - process_file(file_path) + process_file(file_path, total) From 85622dee9c1ffcbd8e407230de4c160e7163f1b2 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Thu, 15 Jan 2026 00:14:49 +0000 Subject: [PATCH 69/69] improve the readability to eliminate misinterpration --- implement-shell-tools/ls/ls.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/implement-shell-tools/ls/ls.py b/implement-shell-tools/ls/ls.py index c2439903..30bcf101 100644 --- a/implement-shell-tools/ls/ls.py +++ b/implement-shell-tools/ls/ls.py @@ -8,7 +8,7 @@ parser.add_argument("-1", "--one", dest="one", help="Output one entry per line", action="store_true") parser.add_argument("-a", help="List all files & directories, including hidden ones", action="store_true") -parser.add_argument("paths", nargs="*", default=["."], help="The file path to read from") +parser.add_argument("paths", nargs="*", default=["."], help="The file(s) or directories to list") args = parser.parse_args()