From 53fa60024ad7607bc039228406a1aa81b0deeff7 Mon Sep 17 00:00:00 2001 From: zohrehKazemianpour <129424353+zohrehKazemianpour@users.noreply.github.com> Date: Sun, 23 Nov 2025 14:44:31 +0000 Subject: [PATCH 01/10] Add prep to gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 3c3629e6..cc8b5568 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ node_modules +prep/ From 6a33a5e5f786f565b02cd66b097fad7e55b20d89 Mon Sep 17 00:00:00 2001 From: zohrehKazemianpour <129424353+zohrehKazemianpour@users.noreply.github.com> Date: Sun, 23 Nov 2025 19:37:42 +0000 Subject: [PATCH 02/10] Implement basic cat command in Python --- implement-shell-tools/cat/cat.py | 8 ++++++++ 1 file changed, 8 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..757c15e0 --- /dev/null +++ b/implement-shell-tools/cat/cat.py @@ -0,0 +1,8 @@ +import sys + +filename = sys.argv[1] + +with open(filename, "r") as f: + content = f.read() + +print(content) From d1c13548d71817726d2972fbedcb8e2e380c938a Mon Sep 17 00:00:00 2001 From: zohrehKazemianpour <129424353+zohrehKazemianpour@users.noreply.github.com> Date: Sun, 23 Nov 2025 20:25:29 +0000 Subject: [PATCH 03/10] Add -n flag to number lines in cat command --- implement-shell-tools/cat/cat.py | 33 ++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/implement-shell-tools/cat/cat.py b/implement-shell-tools/cat/cat.py index 757c15e0..0b4a7943 100644 --- a/implement-shell-tools/cat/cat.py +++ b/implement-shell-tools/cat/cat.py @@ -1,8 +1,33 @@ import sys +import argparse -filename = sys.argv[1] +# Setup argument parser +parser = argparse.ArgumentParser( + prog="cat", + description="Concatenate and display files" +) + +parser.add_argument("-n", "--number", action="store_true", help="Number all output lines") +parser.add_argument("path", help="File to read") + +args = parser.parse_args() + + +# Read the file +with open(args.path, "r") as f: + content = f.read() -with open(filename, "r") as f: - content = f.read() -print(content) +# Check if numbering is needed +if args.number: + lines = content.split("\n") + numbered_lines = [] + + for index, line in enumerate(lines): + line_number = index + 1 + numbered_line = f"{line_number:6}\t{line}" # Format with tab like real cat + numbered_lines.append(numbered_line) + + print("\n".join(numbered_lines)) +else: + print(content) From 6607cde2b1ccddbde7c5037d76cbdfd0b682e2d0 Mon Sep 17 00:00:00 2001 From: zohrehKazemianpour <129424353+zohrehKazemianpour@users.noreply.github.com> Date: Sun, 23 Nov 2025 20:42:14 +0000 Subject: [PATCH 04/10] Add -b flag to number only non-empty lines --- implement-shell-tools/cat/cat.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/implement-shell-tools/cat/cat.py b/implement-shell-tools/cat/cat.py index 0b4a7943..8f08038a 100644 --- a/implement-shell-tools/cat/cat.py +++ b/implement-shell-tools/cat/cat.py @@ -8,11 +8,11 @@ ) parser.add_argument("-n", "--number", action="store_true", help="Number all output lines") +parser.add_argument("-b", "--number-nonblank", action="store_true", help="Number non-empty lines only") parser.add_argument("path", help="File to read") args = parser.parse_args() - # Read the file with open(args.path, "r") as f: content = f.read() @@ -29,5 +29,21 @@ numbered_lines.append(numbered_line) print("\n".join(numbered_lines)) + +elif args.number_nonblank: + lines = content.split("\n") + numbered_lines = [] + line_number = 0 + + for line in lines: + if line.strip() == "": # Empty line + numbered_lines.append(line) # Don't number it + else: # Non-empty line + line_number = line_number + 1 + numbered_line = f"{line_number:6}\t{line}" + numbered_lines.append(numbered_line) + + print("\n".join(numbered_lines)) + else: print(content) From d1ed6cac71e6c2a935220cac8259d57f294b106d Mon Sep 17 00:00:00 2001 From: zohrehKazemianpour <129424353+zohrehKazemianpour@users.noreply.github.com> Date: Sun, 23 Nov 2025 21:20:46 +0000 Subject: [PATCH 05/10] Add support for multiple files in cat command --- implement-shell-tools/cat/cat.py | 59 ++++++++++++++++---------------- 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/implement-shell-tools/cat/cat.py b/implement-shell-tools/cat/cat.py index 8f08038a..108678d9 100644 --- a/implement-shell-tools/cat/cat.py +++ b/implement-shell-tools/cat/cat.py @@ -9,41 +9,42 @@ parser.add_argument("-n", "--number", action="store_true", help="Number all output lines") parser.add_argument("-b", "--number-nonblank", action="store_true", help="Number non-empty lines only") -parser.add_argument("path", help="File to read") +parser.add_argument("paths", nargs='+', help="Files to read") args = parser.parse_args() -# Read the file -with open(args.path, "r") as f: - content = f.read() - +line_number = 0 # Shared counter across all files -# Check if numbering is needed -if args.number: - lines = content.split("\n") - numbered_lines = [] +# Process each file +for path in args.paths: # LEVEL 1: for loop starts + with open(path, "r") as f: # LEVEL 2: inside for loop + content = f.read() # LEVEL 3: inside with block - for index, line in enumerate(lines): - line_number = index + 1 - numbered_line = f"{line_number:6}\t{line}" # Format with tab like real cat - numbered_lines.append(numbered_line) - - print("\n".join(numbered_lines)) - -elif args.number_nonblank: - lines = content.split("\n") - numbered_lines = [] - line_number = 0 - - for line in lines: - if line.strip() == "": # Empty line - numbered_lines.append(line) # Don't number it - else: # Non-empty line - line_number = line_number + 1 + # Check if numbering is needed + if args.number: # LEVEL 2: inside for loop + lines = content.split("\n") # LEVEL 3: inside if + numbered_lines = [] + + for index, line in enumerate(lines): # LEVEL 3: inside if + line_number = line_number + 1 # LEVEL 4: inside inner for numbered_line = f"{line_number:6}\t{line}" numbered_lines.append(numbered_line) + + print("\n".join(numbered_lines)) # LEVEL 3: inside if - print("\n".join(numbered_lines)) + elif args.number_nonblank: # LEVEL 2: inside for loop + lines = content.split("\n") # LEVEL 3: inside elif + numbered_lines = [] + + for line in lines: # LEVEL 3: inside elif + if line.strip() == "": # LEVEL 4: inside inner for + numbered_lines.append(line) + else: + line_number = line_number + 1 + numbered_line = f"{line_number:6}\t{line}" + numbered_lines.append(numbered_line) + + print("\n".join(numbered_lines)) -else: - print(content) + else: # LEVEL 2: inside for loop + print(content) # LEVEL 3: inside else \ No newline at end of file From ba64d2860fdca19fa71f457794a1a36f00c85f2e Mon Sep 17 00:00:00 2001 From: zohrehKazemianpour <129424353+zohrehKazemianpour@users.noreply.github.com> Date: Sun, 23 Nov 2025 22:31:34 +0000 Subject: [PATCH 06/10] implement ls-1 command --- implement-shell-tools/ls/ls.py | 20 ++++++++++++++++++++ 1 file changed, 20 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..613cd5a4 --- /dev/null +++ b/implement-shell-tools/ls/ls.py @@ -0,0 +1,20 @@ +import os +import argparse + +# Setup argument parser +parser = argparse.ArgumentParser( + prog="ls", + description="Lists contents of a directory" +) + +parser.add_argument("-1", dest="one_column", action="store_true", help="List one file per line") +parser.add_argument("path", nargs='?', default=".", help="Directory to list (default: current directory)") + +args = parser.parse_args() + +# List directory contents +files = os.listdir(args.path) + +# Print each file +for file in files: + print(file) \ No newline at end of file From 37c7132ffae6e6ace1feb1404518dcd516b35017 Mon Sep 17 00:00:00 2001 From: zohrehKazemianpour <129424353+zohrehKazemianpour@users.noreply.github.com> Date: Sun, 23 Nov 2025 22:37:23 +0000 Subject: [PATCH 07/10] Add -a flag to ls to show hidden files --- implement-shell-tools/ls/ls.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/implement-shell-tools/ls/ls.py b/implement-shell-tools/ls/ls.py index 613cd5a4..c99aaea3 100644 --- a/implement-shell-tools/ls/ls.py +++ b/implement-shell-tools/ls/ls.py @@ -8,6 +8,7 @@ ) parser.add_argument("-1", dest="one_column", action="store_true", help="List one file per line") +parser.add_argument("-a", "--all", action="store_true", help="Include hidden files") parser.add_argument("path", nargs='?', default=".", help="Directory to list (default: current directory)") args = parser.parse_args() @@ -15,6 +16,9 @@ # List directory contents files = os.listdir(args.path) -# Print each file +# Filter out hidden files unless -a flag is used +if not args.all: + files = [f for f in files if not f.startswith('.')] + for file in files: print(file) \ No newline at end of file From 5d1476bb17005a7e926656daecaf6d5d4817f698 Mon Sep 17 00:00:00 2001 From: zohrehKazemianpour <129424353+zohrehKazemianpour@users.noreply.github.com> Date: Mon, 24 Nov 2025 13:32:40 +0000 Subject: [PATCH 08/10] Implement basic wc command in Python --- implement-shell-tools/wc/wc.py | 22 ++++++++++++++++++++++ 1 file changed, 22 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..6d534920 --- /dev/null +++ b/implement-shell-tools/wc/wc.py @@ -0,0 +1,22 @@ +import argparse + +# Setup argument parser +parser = argparse.ArgumentParser( + prog="wc", + description="Count lines, words, and characters" +) +parser.add_argument("paths", nargs='+', help="Files to count") + +args = parser.parse_args() + +for path in args.paths: + # Read the file + with open(path, "r") as f: + content = f.read() + + # Count lines, words, characters + lines = len(content.rstrip('\n').split('\n')) + words = len(content.split()) + chars = len(content) + + print(f"{lines:8}{words:8}{chars:8} {path}") \ No newline at end of file From df5b8e52d4de7c1ff58b14ccea03e1dd7754b7c1 Mon Sep 17 00:00:00 2001 From: zohrehKazemianpour <129424353+zohrehKazemianpour@users.noreply.github.com> Date: Mon, 24 Nov 2025 13:36:30 +0000 Subject: [PATCH 09/10] Implement wc command with -l, -w, and -c flags --- implement-shell-tools/wc/wc.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/implement-shell-tools/wc/wc.py b/implement-shell-tools/wc/wc.py index 6d534920..329e4512 100644 --- a/implement-shell-tools/wc/wc.py +++ b/implement-shell-tools/wc/wc.py @@ -6,6 +6,9 @@ description="Count lines, words, and characters" ) parser.add_argument("paths", nargs='+', help="Files to count") +parser.add_argument("-l", "--lines", action="store_true", help="Count lines only") +parser.add_argument("-w", "--words", action="store_true", help="Count words only") +parser.add_argument("-c", "--chars", action="store_true", help="Count characters only") args = parser.parse_args() @@ -19,4 +22,11 @@ words = len(content.split()) chars = len(content) - print(f"{lines:8}{words:8}{chars:8} {path}") \ No newline at end of file + if args.lines: + print(f"{lines:8} {path}") + elif args.words: + print(f"{words:8} {path}") + elif args.chars: + print(f"{chars:8} {path}") + else: + print(f"{lines:8}{words:8}{chars:8} {path}") \ No newline at end of file From 36020221416b0290b903d3d22db2d41daffdf335 Mon Sep 17 00:00:00 2001 From: zohrehKazemianpour <129424353+zohrehKazemianpour@users.noreply.github.com> Date: Mon, 24 Nov 2025 13:50:33 +0000 Subject: [PATCH 10/10] Add total line for multiple files in wc --- implement-shell-tools/wc/wc.py | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/implement-shell-tools/wc/wc.py b/implement-shell-tools/wc/wc.py index 329e4512..f3e00f0a 100644 --- a/implement-shell-tools/wc/wc.py +++ b/implement-shell-tools/wc/wc.py @@ -12,6 +12,11 @@ args = parser.parse_args() +# Track totals +total_lines = 0 +total_words = 0 +total_chars = 0 + for path in args.paths: # Read the file with open(path, "r") as f: @@ -22,6 +27,11 @@ words = len(content.split()) chars = len(content) + # Add to totals + total_lines += lines + total_words += words + total_chars += chars + if args.lines: print(f"{lines:8} {path}") elif args.words: @@ -29,4 +39,17 @@ elif args.chars: print(f"{chars:8} {path}") else: - print(f"{lines:8}{words:8}{chars:8} {path}") \ No newline at end of file + print(f"{lines:8}{words:8}{chars:8} {path}") + + +# Print totals if multiple files +if len(args.paths) > 1: + if args.lines: + print(f"{total_lines:8} total") + elif args.words: + print(f"{total_words:8} total") + elif args.chars: + print(f"{total_chars:8} total") + else: + print(f"{total_lines:8}{total_words:8}{total_chars:8} total") +